Создать интервальную переменную каждые x строк в dplyr

#r #dplyr #grouping #sequence

#r #dplyr #группировка #последовательность

Вопрос:

Какой наиболее эффективный способ создать новую переменную, которая увеличивается на x единиц после каждых x строк? Например, у меня есть фрейм данных:

  d <- data.frame(group_var = c('a', 'b', 'c'),
             y = c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,  1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21))
 

И я хотел бы создать новую переменную, которая начинается с x и увеличивается на x каждые x строк, чтобы я получил такой фрейм данных:

  d <- data.frame(group_var = c('a', 'b', 'c'),
 y = c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,
       1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,      
       1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21),
 z = c(5,5,5,5,5,10,10,10,10,10,15,15,15,15,15,20,20,20,20,20,20,5,5,5,5,5,10,10,10,10,10,15,15,15,15,15,20,20,20,20,20,20,5,5,5,5,5,10,10,10,10,10,15,15,15,15,15,20,20,20,20,20,20))
 

Кроме того, когда у меня есть остатки, как и в предыдущем фрейме данных, я бы хотел, чтобы они были упорядочены с предыдущей группой (так что y = 11 будет z = 10). Обратите внимание, что мой целевой фрейм данных сохраняет то же количество строк, что и исходный фрейм данных.

Ответ №1:

Мы можем создать группирующую переменную diff на основе on ‘y’, затем создать ‘z’ с gl помощью и умножить на 5

 library(dplyr)
library(tidyr)
d1 <- d %>% 
    group_by(grp = cumsum(c(TRUE, diff(y) < 0))) %>% 
    mutate(z = as.integer(gl(n(), 5, n())) * 5,
          z = replace(z,  ave(z, z, FUN = length) < 5, NA)) %>% 
    ungroup %>% 
    fill(z) %>%
    select(-grp)
 

-вывод

 as.data.frame(d1)
   group_var  y  z
1          a  1  5
2          b  2  5
3          c  3  5
4          a  4  5
5          b  5  5
6          c  6 10
7          a  7 10
8          b  8 10
9          c  9 10
10         a 10 10
11         b 11 15
12         c 12 15
13         a 13 15
14         b 14 15
15         c 15 15
16         a 16 20
17         b 17 20
18         c 18 20
19         a 19 20
20         b 20 20
21         c 21 20
22         a  1  5
23         b  2  5
24         c  3  5
25         a  4  5
26         b  5  5
27         c  6 10
28         a  7 10
29         b  8 10
30         c  9 10
31         a 10 10
32         b 11 15
33         c 12 15
34         a 13 15
35         b 14 15
36         c 15 15
37         a 16 20
38         b 17 20
39         c 18 20
40         a 19 20
41         b 20 20
42         c 21 20
43         a  1  5
44         b  2  5
45         c  3  5
46         a  4  5
47         b  5  5
48         c  6 10
49         a  7 10
50         b  8 10
51         c  9 10
52         a 10 10
53         b 11 15
54         c 12 15
55         a 13 15
56         b 14 15
57         c 15 15
58         a 16 20
59         b 17 20
60         c 18 20
61         a 19 20
62         b 20 20
63         c 21 20
 

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

1. В идеале я хотел бы автоматизировать это вместо жесткого кодирования повторений, поскольку реальный фрейм данных намного, намного больше.

2. Да, но это пример фрейма данных. В реальном фрейме данных y может достигать 200 в зависимости от идентификатора group_var . Поэтому я не хочу вручную кодировать 5, 10, 15, 20 и т.д.

3. Это был пример фрейма данных. Я отредактировал ее так, чтобы z увеличилось до 15 или 20. Я хотел автоматизировать этот процесс, поэтому я обратился за помощью.

4. Хорошо, опять же, я не хочу жестко кодировать приращения. Каждые 5 строк я хотел бы добавить 5 к y, независимо от того, сколько строк в сгруппированной переменной. Поэтому я не просто хочу написать вектор из 5, 10, 15, 20.

5. Потому что есть остаток, о котором я также спрашивал в исходном вопросе. 21 строка = последняя строка будет сгруппирована с предыдущим значением y.