#r #dplyr
#r #dplyr
Вопрос:
У меня есть следующий фрейм данных:
df <- data.frame(ID=c(rep(c("A"),8),rep(c("B"),8)),
Datetime=c("2020-08-05 12:00:00","2020-08-05 17:00:00","2020-08-05 18:03:00","2020-08-05 22:54:00","2020-08-06 01:08:00","2020-08-06 13:26:00","2020-08-06 19:04:00","2020-08-08 11:00:00",
"2020-08-04 03:00:00","2020-08-04 15:00:00","2020-08-04 23:00:00","2020-08-06 14:00:00","2020-08-06 17:00:00","2020-08-06 20:00:00","2020-08-07 04:00:00","2020-08-07 16:00:00"),
Period=c("Day","Day","Day","Night","Night","Day","Night","Day","Night","Day","Night","Day","Day","Night","Night","Day"),
State=c(1,2,1,1,1,1,2,2,1,1,1,2,2,1,1,1),
Acc=c(1.1,2.3,1.7,1.4,0.1,1.9,2.9,2.3,1.1,0.1,1.4,0.2,2.6,1.3,1.7,1.0))
df$Datetime <- as.POSIXct(df$Datetime,format="%Y-%m-%d %H:%M:%S", tz="UTC")
df
ID Datetime Period State Acc
1 A 2020-08-05 12:00:00 Day 1 1.1
2 A 2020-08-05 17:00:00 Day 2 2.3
3 A 2020-08-05 18:03:00 Day 1 1.7
4 A 2020-08-05 22:54:00 Night 1 1.4
5 A 2020-08-06 01:08:00 Night 1 0.1
6 A 2020-08-06 13:26:00 Day 1 1.9
7 A 2020-08-06 19:04:00 Night 2 2.9
8 A 2020-08-08 11:00:00 Day 2 2.3
9 B 2020-08-04 03:00:00 Night 1 1.1
10 B 2020-08-04 15:00:00 Day 1 0.1
11 B 2020-08-04 23:00:00 Night 1 1.4
12 B 2020-08-06 14:00:00 Day 2 0.2
13 B 2020-08-06 17:00:00 Day 2 2.6
14 B 2020-08-06 20:00:00 Night 1 1.3
15 B 2020-08-07 04:00:00 Night 1 1.7
16 B 2020-08-07 16:00:00 Day 1 1.0
Мне нужно оценить среднее значение Acc
per ID
, day
, Period
и State
. Мне понадобится такой фрейм данных:
ID Datetime State.1_day State.1_night State.2_day State.2_night
1 A 2020-08-04 NA NA NA NA # This day there was no data for `A`, but there was for `B`.
2 A 2020-08-05 1.4 1.4 2.3 NA
. . . . . . .
. . . . . . .
. . . . . . .
Кто-нибудь знает, как это получить? Я не знаю, как вычислить среднее значение, используя все эти переменные сразу, а затем создать столбцы, которые я показал.
Заранее спасибо
Ответ №1:
Вот один из подходов с использованием tidyverse. Если вы хотите показать все дни, даже если они отсутствуют для некоторых идентификаторов, тогда используйте второй подход.
library(tidyverse)
# your data
df <- data.frame(ID=c(rep(c("A"),8),rep(c("B"),8)),
Datetime=c("2020-08-05 12:00:00","2020-08-05 17:00:00","2020-08-05 18:03:00","2020-08-05 22:54:00","2020-08-06 01:08:00","2020-08-06 13:26:00","2020-08-06 19:04:00","2020-08-08 11:00:00",
"2020-08-04 03:00:00","2020-08-04 15:00:00","2020-08-04 23:00:00","2020-08-06 14:00:00","2020-08-06 17:00:00","2020-08-06 20:00:00","2020-08-07 04:00:00","2020-08-07 16:00:00"),
Period=c("Day","Day","Day","Night","Night","Day","Night","Day","Night","Day","Night","Day","Day","Night","Night","Day"),
State=c(1,2,1,1,1,1,2,2,1,1,1,2,2,1,1,1),
Acc=c(1.1,2.3,1.7,1.4,0.1,1.9,2.9,2.3,1.1,0.1,1.4,0.2,2.6,1.3,1.7,1.0))
df$Datetime <- as.POSIXct(df$Datetime,format="%Y-%m-%d %H:%M:%S", tz="UTC")
# first approach
df %>%
group_by(ID, Day = as.Date(Datetime), Period, State) %>%
summarise(Acc = mean(Acc, na.rm = TRUE)) %>%
pivot_wider(names_from = c(State, Period),
values_from = Acc,
names_prefix = "State.")
#> `summarise()` regrouping output by 'ID', 'Day', 'Period' (override with `.groups` argument)
#> # A tibble: 6 x 6
#> # Groups: ID, Day [6]
#> ID Day State.1_Day State.2_Day State.1_Night State.2_Night
#> <chr> <date> <dbl> <dbl> <dbl> <dbl>
#> 1 A 2020-08-05 1.4 2.3 1.4 NA
#> 2 A 2020-08-06 1.9 NA 0.1 2.9
#> 3 A 2020-08-08 NA 2.3 NA NA
#> 4 B 2020-08-04 0.1 NA 1.25 NA
#> 5 B 2020-08-06 NA 1.4 1.3 NA
#> 6 B 2020-08-07 1 NA 1.7 NA
# second approach
df %>%
group_by(ID, Day = as.factor(as.Date(Datetime)), Period, State, .drop = FALSE) %>%
summarise(Acc = mean(Acc, na.rm = TRUE)) %>%
pivot_wider(names_from = c(State, Period),
values_from = Acc,
names_prefix = "State.") %>%
select(!State.NA_NA)
#> `summarise()` regrouping output by 'ID', 'Day', 'Period' (override with `.groups` argument)
#> # A tibble: 10 x 6
#> # Groups: ID, Day [10]
#> ID Day State.1_Day State.2_Day State.1_Night State.2_Night
#> <chr> <fct> <dbl> <dbl> <dbl> <dbl>
#> 1 A 2020-08-04 NA NA NA NA
#> 2 A 2020-08-05 1.4 2.3 1.4 NA
#> 3 A 2020-08-06 1.9 NA 0.1 2.9
#> 4 A 2020-08-07 NA NA NA NA
#> 5 A 2020-08-08 NA 2.3 NA NA
#> 6 B 2020-08-04 0.1 NA 1.25 NA
#> 7 B 2020-08-05 NA NA NA NA
#> 8 B 2020-08-06 NA 1.4 1.3 NA
#> 9 B 2020-08-07 1 NA 1.7 NA
#> 10 B 2020-08-08 NA NA NA NA
Создано 2020-11-10 пакетом reprex (версия 0.3.0)
Комментарии:
1. Спасибо @TimTeaFan, вы знаете, как включить тот же диапазон дат для
A
иB
? Я хочу построить график этих значений сверхурочно для разных людей, и было бы полезно, если бы для всех из них даты были одинаковыми. В этом примере мне нужно было бы иметь для каждойID
даты между2020-08-04
и2020-08-08
. Возможно ли это?2. Вы видели мой второй подход? В нем должны быть указаны все даты для каждой
ID
. Я преобразую дату в коэффициент, а затем использую.drop = FALSE
аргумент ingroup_by
.3. Извините, я этого не видел! Теперь это выглядит идеально. Спасибо за ваше время и этот замечательный ответ.
4. Нет проблем, я обновил сразу после моего первоначального сообщения 😉
5. Привет @TimTeaFan, теперь я использую предложенный вами код. Вот почему я еще не поставил вам зеленую отметку. Однако я обнаружил проблему. При использовании вашего второго подхода я получаю сообщение об ошибке, в нем говорится: «Ошибка в map_lgl (.x, .p, …): состояние объекта «не найдено». Вы знаете, почему? Я предполагаю, что это должно быть что-то глупое, но я не понимаю, что.