Данные тегов/групп внутри набора данных в соответствии со следующей строкой

#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 .