У меня есть фрейм данных, который выглядит так:
structure(list(datetime = structure(c(1559347200, 1559350800,
1559354400, 1559358000, 1559361600, 1559365200, 1559368800, 1559372400,
1559376000, 1559379600), tzone = "UTC", class = c("POSIXct",
"POSIXt")), BUSwt = c(77.8154, 77.2538, 76.9325, 76.81235, 76.6544,
76.3403, 76.16165, 76.22375, 76.47035, 76.74395), MBwt = c(78.3653,
78.53495, 78.6074, 78.30725, 78.0368, 77.9477, 77.8946, 77.927,
78.12455, 78.23615), SUSwt = c(76.2575, 76.0055, 75.7265, 75.425,
75.137, 74.849, 74.651, 74.624, 74.696, 74.8535)), row.names = c(NA,
-10L), class = c("tbl_df", "tbl", "data.frame"))
Он содержит данные даты и времени за 5 лет для трех столбцов переменных «BUSwt», «MBwt» и «SUSwt». Я хочу рассчитать среднее, минимальное и максимальное значение этой переменной для каждой конкретной даты и часа в течение 5 лет данных. Пример этих данных будет выглядеть так:
Мой текущий код для создания фрейма данных выглядит следующим образом:
WaterData <- BUSdata %>%
left_join(MBdata, by = "datetime") %>%
left_join(SUSdata, by = "datetime")
Есть ли способ сделать это, продолжая работу в трубе?
Я тоже не понимаю. Есть ли в ваших данных несколько строк для каждого часа (ваш пример этого не отражает)? Если это так, вы можете округлить по часам. См. этот раздел R для науки о данных: r4ds.hadley.nz/datetimes#rounding
Сколько наборов данных у вас есть, 3? В описании вашей проблемы не предлагается left_join
(или какой-либо другой вид соединения) в качестве решения.
Проблема в том, что вы хотите группировать данные по месяцам/дням/часам, а не по годам?
Правильно, я хочу посмотреть среднее, максимальное и минимальное значение по месяцу/дню/часу, но не по году.
Вот решение, если я правильно понимаю проблему.
Я предполагаю, что проблема заключается в вычислении агрегированной статистики по дате/часу.
library(tidyverse)
BUSdata %>%
pivot_longer(-datetime) %>%
mutate(datehour = format(datetime, "%m-%d %H")) %>%
summarise(
mean = mean(value, na.rm = TRUE),
min = min(value, na.rm = TRUE),
max = max(value, na.rm = TRUE),
.by = c(datehour, name)
) %>%
pivot_longer(-c(datehour, name), names_to = "stats") %>%
pivot_wider(
id_cols = datehour,
names_from = c(name, stats),
values_from = value
)
Еще один способ получить то, что вам нужно, используя удобную функцию dplyr
across()
:
library(tidyverse)
df %>%
mutate(month = month(datetime),
day = day(datetime),
hour = hour(datetime)) %>%
group_by(month, day, hour) %>%
summarise(across(.cols = c("BUSwt", "MBwt", "SUSwt"),
.fns = list("min" = min, "mean" = mean, "max" = max))) %>%
ungroup()
Это решение разделяет месяц, день и час на отдельные столбцы. Если вам действительно нужен формат даты (например, для построения графиков), вы можете привести все к одному и тому же году (неважно, какой это год), вот так:
df %>%
mutate(datetime = `year<-`(datetime, 2000)) %>%
group_by(datetime) %>%
summarise(across(.cols = c("BUSwt", "MBwt", "SUSwt"),
.fns = list("min" = min, "mean" = mean, "max" = max))) %>%
ungroup()
Этот вопрос отличается тем, что основная цель состоит не в том, как агрегировать несколько столбцов, а в том, как агрегировать значения этих столбцов по «мм-дд чч:мм:сс» для всего набора данных.