#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
Различия между моими и приведенными выше ответами заключаются в том, что я перевел даты из символов, поэтому они отсортированы иначе, чем в виде текста.