Назначить возрастающий индекс для каждой группы в сгруппированном фрейме данных в R

#r #dplyr #group-by

#r #dplyr #группировать по

Вопрос:

У меня есть фрейм данных / tibble, который выглядит следующим образом:

 # A tibble: 15 x 2
# Groups:   id [3]
      id date      
   <int> <date>    
 1     1 1998-02-13
 2     1 1998-02-14
 3     1 1998-02-15
 4     1 1998-02-16
 5     1 1998-02-17
 6     2 1998-02-13
 7     2 1998-02-14
 8     2 1998-02-15
 9     2 1998-02-16
10     2 1998-02-17
11     3 1998-02-13
12     3 1998-02-14
13     3 1998-02-15
14     3 1998-02-16
15     3 1998-02-17
 

Я хотел бы добавить переменную «days_before_event», которая будет считаться от 1: 5 (но это не должно быть жестко запрограммировано, а скорее быть элементами для каждой группы). Я думал о том, чтобы сделать что-то вроде этого

 df_long %>% mutate(days_before_event = 1:nrow(.))
 

где nrow(.) должно быть количество строк в группе. Это не работает и показывает ошибку

 Fehler: Problem with `mutate()` input `days_before_event`.
x Input `days_before_event` can't be recycled to size 5.
i Input `days_before_event` is `1:nrow(.)`.
i Input `days_before_event` must be size 5 or 1, not 15.
i The error occurred in group 1: id = 1.
 

Любой трюк о том, как я могу этого добиться?

Ответ №1:

Мы можем использовать row_number вместо 1:nrow

 library(dplyr)
df_long %>% 
    mutate(days_before_event =row_number())
 

Или с помощью base R , используйте ave для группировки по «идентификатору» и получения последовательности ( seq_along )

 df_long$days_before_event <- with(df_long, ave(seq_along(id),
          id, FUN = seq_along))
 

Ошибка заключается в том, что это сгруппированный набор данных (из атрибута group, отображаемого в печатных данных), поэтому 1:nrow получит последовательность от 1-й до последней строки всего набора данных, а не последней строки группы. Это создает дисбаланс length и mutate может возвращать только выходные данные, совпадающие length с исходными данными (или их нужно переносить в a list )

Комментарии:

1. потрясающе, большое спасибо!! Если бы я хотел использовать базовый r, вы знаете, как я мог бы достичь той же цели?

2. о, вау, большое вам спасибо! База r напрямую выглядит более устрашающе, ха-ха

3. @RobinKohrs В data.table он намного компактнее setDT(df_long)[, days_before_event := rowid(id)]

4. спасибо большое! Я никогда не рассматривал data.table, поскольку на самом деле я не работаю с большими наборами данных. Я думал, что можно отказаться от более простого sytax для более быстрой обработки. Но, возможно, стоит подробнее изучить это:)