Как последовательно измерять 4 строки для кратных переменных

#r #dplyr

#r #dplyr

Вопрос:

Я пытаюсь понять, как я могу последовательно измерить 4 строки для кратных переменных в моей сортировке фреймов данных по дате. Вот игрушечный пример

 test = data.frame(my_groups = c("A", "A", "A", "B", "B", "C", "C", "C", "A", "A","A","A","A","A" , "C"),  measure1 = c(10:24),  measure2 = c(1:15),  time= c("20-09-2020", "25-09-2020", "19-09-2020", "20-05-2020", "20-06-2021",   "11-01-2021", "13-01-2021", "13-01-2021", "15-01-2021", "15-01-2021",  "20-03-2021", "20-10-2021", "29-06-2021", "20-07-2021", "13-06-2021")) # my_groups measure1 measure2 time # 1 A 18 9 15-01-2021 # 2 A 19 10 15-01-2021 # 3 A 12 3 19-09-2020 # 4 A 20 11 20-03-2021 # 5 A 23 14 20-07-2021 # 6 A 10 1 20-09-2020 # 7 A 21 12 20-10-2021 # 8 A 11 2 25-09-2020 # 9 A 22 13 29-06-2021 # 10 B 13 4 20-05-2020 # 11 B 14 5 20-06-2021 # 12 C 15 6 11-01-2021 # 13 C 16 7 13-01-2021 # 14 C 17 8 13-01-2021 # 15 C 24 15 13-06-2021  

В результате я бы хотел что-то вроде:

 # my_groups measure1 measure2 time # 1 A 17.25 8.25 20-03-2021 #mean for the first 4 elements of A and maximun date # 2 A 16.25 7.25 25-09-2020 #mean for the others 4 elements of A and maximun date # 3 C 18 9 13-06-2021 #mean for the first 4 elements of B and maximun date  

Чтобы получить этот результат, я подумал о том, чтобы использовать что-то вроде этого:

 test %gt;%   arrange( my_groups,time) %gt;%   group_by(my_groups) %gt;%   summarise(measure1 = mean(measure1),  measure2 = mean(measure2),   time = max(time))  

Но у меня возникли проблемы с поиском решения для последовательного применения этих мер для 4 значений.

Любой намек на то, как я могу это сделать?

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

1. Вы можете использовать rollapply для этого средства.

2. а на свидание?

3. Я не уверен… может быть, только максимум, может быть, у кого-то есть идея получше

4. в моем реальном случае у a есть много переменных, которые мне нужно понимать под этим значением , а не только measure1 «и measure2 «, но логика будет той же.

Ответ №1:

Мы можем добавить еще одну группирующую переменную g4 , используя целочисленное деление, чтобы гарантировать, что мы получим группы по 4, и, при желании, отбросим группы с меньшим количеством участников. Тогда просто запустите свой summarize .

 library(dplyr)  test %gt;%   arrange(my_groups, time) %gt;%   group_by(my_groups) %gt;%   mutate(g4 = (row_number() - 1) %/% 4) %gt;%  group_by(my_groups, g4) %gt;%  filter(n() == 4) %gt;%  summarise(measure1 = mean(measure1),  measure2 = mean(measure2),   time = max(time),  .groups = "drop") #gt; # A tibble: 3 × 5 #gt; my_groups g4 measure1 measure2 time  #gt; lt;chrgt; lt;dblgt; lt;dblgt; lt;dblgt; lt;chrgt;  #gt; 1 A 0 17.2 8.25 20-03-2021 #gt; 2 A 1 16.2 7.25 25-09-2020 #gt; 3 C 0 18 9 13-06-2021  

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

1. отличная идея! Я попробую это в моем реальном случае. Я не могу использовать элементы, когда у меня нет «полной» группы из 4

2. В таком случае, в чем разница в использовании или нет .groups = "drop" ?

3. @DR15 Он просто явно удаляет группу, в противном случае вы получите небольшое предупреждение о том, что данные перегруппированы my_groups (по умолчанию .groups = "drop_last" ).

4. Работает на меня! Отличное решение!

Ответ №2:

Функция «f» создает скользящее окно (если вы часто выполняете оконную функцию, я действительно рекомендую пакет слайдеров). Функция «g» просто применяет функцию ко всем числовым окнам. Последний шаг group_modify применяет функции к данным и фильтрует хорошие данные.

 library(slider) library(lubridate) library(dplyr) library(tidyr) library(purrr)  test = data.frame(my_groups = c("A", "A", "A", "B", "B", "C", "C", "C", "A", "A","A","A","A","A" , "C"),  measure1 = c(10:24),  measure2 = c(1:15),  time= dmy(c("20-09-2020", "25-09-2020", "19-09-2020", "20-05-2020", "20-06-2021",   "11-01-2021", "13-01-2021", "13-01-2021", "15-01-2021", "15-01-2021",  "20-03-2021", "20-10-2021", "29-06-2021", "20-07-2021", "13-06-2021"))) %gt;%   arrange(my_groups, time) %gt;%  group_by(my_groups)  f lt;- function(x) {t lt;- slide_mean(x, before=3, complete=T, step = 4)} g lt;- function(y) {s lt;- y %gt;% map_if(is.numeric, ~ f(.x)) %gt;% bind_cols()} x lt;- test %gt;% group_modify(~ g(.x)) %gt;% filter(!(is.na(measure1) | is.na(measure2)))   my_groups measure1 measure2 time   lt;chrgt; lt;dblgt; lt;dblgt; lt;dategt;  1 A 12.8 3.75 2021-01-15 2 A 21 12 2021-07-20 3 C 18 9 2021-06-13  

Различия между моими и приведенными выше ответами заключаются в том, что я перевел даты из символов, поэтому они отсортированы иначе, чем в виде текста.