#r
Вопрос:
У меня есть набор данных (сегодня 10e5, ожидается позже 10e6 строк). После группировки набор данных был сокращен до 60 строк. Уменьшенный набор данных выглядит следующим образом ( db.P.sys.a
):
logger ; d; shift
gl240-03 ; 98; D
gl240-03 ; 114; D
gl240-04 ; 107; N1
gl240-04 ; 112; N2
gl240-04 ; 113; N1
gl240-04 ; 113; N2
gl240-04 ; 114; D
gl240-04 ; 114; N1
gl240-04 ; 114; N2
gl240-04 ; 114; T
Теперь мне нужно создать идентификатор, который группирует наблюдения в соответствии с этой логикой:
(для одного и того же регистратора), если сдвиг в строке n равен N2, а сдвиг в строке (n 1) равен N1, а d в строке (n 1) равен d 1, то у них один и тот же идентификатор.
Это выглядит так:
logger ; d; shift; shift_id
gl240-03; 98; D; 1
gl240-03; 114; D; 2
gl240-04; 107; N1; 3
gl240-04; 112; N2; 4
gl240-04; 113; N1; 4
gl240-04; 113; N2; 6
gl240-04; 114; N1; 6
gl240-04; 114; N2; 9
gl240-04; 114; D; 7
gl240-04; 114; T; 10
Для этого я действую таким образом:
#group by logger, d and shift to get less points
db.P.sys.a<-db.P.sys%>%
group_by(logger,d,shift)%>%
summarise()
#create a sequence to tag each futur grouped shifts
db.P.sys.a$shift_id<-seq(1:nrow(db.P.sys.a))
#subset db with only (N1 and N2)
db.P.sys.b<-db.P.sys.a%>%
filter(shift=="N1"|shift=="N2")
#subset db with remaining shifts (D and T)
db.P.sys.c<-db.P.sys.a%>%
filter(shift=="D"|shift=="T")
#loop to group the consecutive N2 and N1 shifts but with d 1 change
for (a in 1:(nrow(db.P.sys.b)-1)){
if((db.P.sys.b$logger[a]==db.P.sys.b$logger[a 1])amp;(db.P.sys.b$d[a]==(db.P.sys.b$d[a 1])-1)amp;(db.P.sys.b$shift[a]=="N2")amp;(db.P.sys.b$shift[a 1]=="N1") ){
db.P.sys.b$shift_id[a 1]=db.P.sys.b$shift_id[a]}
}
#row bind D, T, N1 and N2 tagged shifts
db.P.sys.a<-rbind(db.P.sys.b,db.P.sys.c)
#join to remaining data (-> each observations are tagged with a shift_id)
db.P.sys<-left_join(db.P.sys,db.P.sys.a,by=c("logger","d","shift"))
Итак, теперь все строки исходного набора данных помечены shift_id.
Мой вопрос в том, есть ли более элегантный способ сделать то же самое ? (например, без использования цикла for). Я думаю, db.P.sys
это не имеет отношения к вопросу.
Заранее благодарю вас.
Ответ №1:
Вы можете попробовать этот dplyr
подход =
library(dplyr)
db.P.sys %>%
group_by(logger) %>%
mutate(shift_id = shift == 'N1' amp; lag(shift, default = first(shift)) == 'N2' amp;
d - lag(d, default = first(d)) == 1) %>%
ungroup %>%
mutate(shift_id = cumsum(!shift_id))
shift_id
сохраняется одинаковым, если текущее shift
значение равно 'N1'
( shift == 'N1'
) и предыдущее shift
значение равно 'N2'
( lag(shift) == 'N2'
), а разница между текущим и previous
d
значением равна 1 ( d - lag(d) == 1
) для каждого logger
.