Создать новую переменную count, условную для предыдущих значений в группе - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть датафрейм с группой и идентификатором времени. Теперь я хочу создать новую переменную count, называемую X2, в зависимости от предыдущих значений X1 в каждой группе.

Предположим, у меня есть следующий фрейм данных, переменные group, time, X1 и хочу создать X2. Значение X2 должно быть переменной count, указывающей количество периодов (т. Е. Строк), поскольку X1 последний раз был равен 1 в данной группе. Если все предыдущие значения X1 равны 0, X2 должно отсутствовать.

          group     time       X1        X2 
1          1         1         0         NA  
2          1         2         0         NA  
3          1         3         1         NA  
4          1         4         0         0  
5          1         5         1         1
6          2         1         0         NA  
7          2         2         1         NA  
8          2         3         1         0  
9          2         4         1         0  
10         2         5         0         0  
11         3         1         0         NA  
12         3         2         0         NA  
13         3         3         0         NA  
14         3         4         1         NA  
15         3         5         0         0  
16         4         1         1         NA  
17         4         2         0         0  
18         4         3         0         1  
19         4         4         0         2  
20         4         5         1         3    
data_test <- data.frame(
   group = rep(1:4, each = 5), 
   time = rep(1:5, n = 4), 
   X1 = c(0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1), 
   X2 = c(NA, NA, NA, 0, 1, NA, NA, 0, 0, 0, NA, NA, NA, NA, 0, NA, 0, 1, 2, 3))

Я мог бы легко создать NA, используя команду if с cumsum()==0. Тем не менее, я понятия не имею, как приблизиться к другой части, то есть создать счет.

Любая помощь будет высоко ценится - если это вообще возможно, используя dplyr.

Большое спасибо .

Ответы [ 2 ]

1 голос
/ 09 апреля 2020

Это не очень элегантно, но включает в себя правила, представленные, я думаю.

Добавлен столбец для номеров строк, где X1 равно 1, а fill используется, чтобы вы могли использовать самый последний номер строки, доступный для этого условия.

Чтобы вычислить X2_new, если X1 равно 0, это разница между текущим номером строки в группе минус последний номер строки, где X1 было 1. Если X1 равно 1 (и не является первым X1 из 1 в группе), выполните аналогичные вычисления, но с предыдущей ссылкой rn.

library(tidyverse)

data_test %>%
  group_by(group) %>%
  mutate(rn = ifelse(X1 == 1, row_number(), NA)) %>%
  fill(rn) %>%
  mutate(X2_new = ifelse(X1 == 0 & row_number() > rn, row_number() - rn - 1, NA),
         X2_new = ifelse(X1 == 1 & !is.na(lag(rn)), row_number() - lag(rn) - 1, X2_new)) %>%
  select(-rn)

Выход

# A tibble: 20 x 5
# Groups:   group [4]
   group  time    X1    X2 X2_new
   <int> <int> <dbl> <dbl>  <dbl>
 1     1     1     0    NA     NA
 2     1     2     0    NA     NA
 3     1     3     1    NA     NA
 4     1     4     0     0      0
 5     1     5     1     1      1
 6     2     1     0    NA     NA
 7     2     2     1    NA     NA
 8     2     3     1     0      0
 9     2     4     1     0      0
10     2     5     0     0      0
11     3     1     0    NA     NA
12     3     2     0    NA     NA
13     3     3     0    NA     NA
14     3     4     1    NA     NA
15     3     5     0     0      0
16     4     1     1    NA     NA
17     4     2     0     0      0
18     4     3     0     1      1
19     4     4     0     2      2
20     4     5     1     3      3
0 голосов
/ 09 апреля 2020

Использование функций pipe (%>%), mutate, group_by и lag из пакета dplyr

library(dplyr)
data_test %>%
  group_by(group) %>%
  mutate(X2 = ifelse(lag(X1) == 1, 0, lag(X2) + 1))

Предполагается, что разница в time будет всегда быть 1, как показано в ваших данных образца. Если time изменяется в ваших данных и X2 должно отражать разницу в time:

data_test %>%
  group_by(group) %>%
  mutate(X2 = ifelse(lag(X1) == 1, 0, lag(X2) + (time - lag(time))))
...