我有一个类似于下面的 xdata tibble 的数据集。当开始日期的月份与日期的月份不同时,我想计算在开始日期定义的日期和五天后的开始日期之间的值变量的平均值。
[为清晰起见而编辑]
library(lubridate)
library(tibble)
xdata <- tibble(date=ymd('2015-01-01')+days(seq(1:(365*3))), values=seq(1,365*3))
xdata <- xdata %>% mutate(start_date = case_when(wday(date)==2 ~ date+days(14))) %>%
fill(start_date)
xdata %>% mutate(avg = case_when(month(start_date) != month(date) ~ mean(values[between(date, start_date, start_date+days(5))])))
我也试过
xdata %>% group_by(start_date) %>% mutate( . . .
但这并不能解决问题。
我期待的是以下内容: 第一个非 NA start_date 出现在第 4 行并且是 start_date='2015-01-19'
我想计算 date='2015-01-19' 和接下来 4 天的值(数据列)的平均值。这些值是 18、19、20、21 和 22。平均值应该是 20。
计算由基于 start_date 的范围定义的日期之间的平均值的最佳方法是什么?
谢谢,
jfd118
答案- Jon Spring 带领我找到了解决方案:
xdata %>%
filter(!is.na(start_date)) %>%
mutate(avg = slide_index_dbl(values, date, mean, .before=1, .after = 5)) %>%
select(start_date = date, avg) %>%
right_join(xdata ) %>%
select(date, values, everything()) %>%
arrange(date) %>% View()
答案 0 :(得分:0)
这会在行中放置一个 NA,开始日期的月份与日期的月份相同。请注意,在您的玩具数据集中,日子总是相隔 7 天,因此代码实际上不会捕获接下来五天内的任何日子。
val=numeric()
for (i in 1:nrow(xdata)) {
if (is.na(xdata$start_date[i]) | month((xdata$date)[i])==month((xdata$start_date)[i])) {
val[i]=NA
} else {
dat=filter(xdata, start_date >= (xdata$start_date)[i] & start_date<= (xdata$start_date)[i]+5)
val[i]=mean(dat$values)
}
}
xdata2=mutate(xdata, val)
答案 1 :(得分:0)
这是一种使用 slider
的方法,它非常适合这样的窗口计算。我不知道如何跳过 NA start_date 行的滑块计算,因此这会将它们过滤掉,然后通过连接将它们带回来:
library(slider); library(lubridate); library(dplyr)
xdata %>%
filter(!is.na(start_date), month(start_date) != month(date)) %>%
mutate(avg = slide_index_dbl(values, start_date, .after = 4, mean)) %>%
right_join(xdata) %>% arrange(date)
编辑:
我想我现在明白了。在这里,我使用 date
计算“当前 + 未来 4 天平均值”,然后重命名该 start_date
以加入原始数据。
library(dplyr); library(slider)
xdata %>%
filter(!is.na(start_date)) %>%
mutate(avg = slide_index_dbl(values, date, .after = 4, mean)) %>%
select(start_date = date, avg) %>%
right_join(xdata ) %>%
select(date, values, everything()) %>%
arrange(date) %>% View()