【问题标题】:Calculate average of variable between two dates based on a different date column根据不同的日期列计算两个日期之间变量的平均值
【发布时间】:2021-03-01 21:52:57
【问题描述】:

我有一个类似于下面的 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()

【问题讨论】:

  • 我不确定我是否理解了这个问题。当开始日期月份与日期月份匹配时,输出应该是什么?你希望输出是什么样的?能举个例子吗?
  • 谢谢乔恩。当 month(start_date) != month(date) 我想计算从 start_date 开始的 5 天内变量“值”的平均值。

标签: r dplyr


【解决方案1】:

这是一种使用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()

【讨论】:

  • 乔恩,谢谢。你的答案有真正的希望。但我不太明白它在做什么。如果在创建 xdata 时,将“values=rnorm(365*3, 1,5)”更改为“values=seq(1, 365*3)”。使用您的代码运行此示例,第一次计算 avg 的结果是 avg=21 on date=2015-01-19, start_date=02-02-2015。我的理解是 slide_index_dbl 函数正在计算从 start_date=02-02-2015 开始的平均值。但是,2015 年 2 月 2 日的值 = 32。平均值太低。对 slide_index_dbl 的调用不应该计算从 02-02-15 到 02-06-2015 的平均值吗?
  • 它目前按start_date 编制索引,对于具有当前start_date 的所有内容的平均值为values,直到5 天后(包括5 天)。所以在这种情况下,它抓取 18:24 的行,日期为 1/19 到 1/24,start_date 均为 2/02,平均 18:24 = 21。您期望什么输出?你能举个例子吗?
  • 编辑后的答案,你现在期待什么?
  • 我明白了。我想要的是从 date=start_date 开始的 5 天的平均值。换句话说,start_date 定义了在 date + (date + days(5)) 上的 5 天平均周期的第一个日期,以使用 lubridate 语法。这有意义吗?
  • 乔恩,为了清楚起见,我编辑了原始问题。谢谢。
【解决方案2】:

这会在开始日期的月份与日期的月份相同的行中放置一个 NA。请注意,在您的玩具数据集中,这些日子总是相隔 7 天,因此代码实际上并没有捕捉到接下来 5 天内的任何日子。

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)

【讨论】:

    猜你喜欢
    • 2016-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 2016-02-24
    • 1970-01-01
    相关资源
    最近更新 更多