给定不同的开始和结束日期,找出每个变量的日平均值

Given different start and end dates, find the daily average of each variable

我有不同开始日期和结束日期的数据。

mydata <- data.frame(id=c(1,2,3), start=c("2010/01/01","2010/01/01","2010/01/02"), end=c("2010/01/01","2010/01/05","2010/01/03"), a=c(140,750,56),b=c(48,25,36))
mydata

  id      start        end   a  b
1  1 2010-01-01 2010-01-01 140 48
2  2 2010-01-01 2010-01-05 750 25
3  3 2010-01-02 2010-01-03  56 36

我想求每天变量 ab 的平均值。下面我通过展开具有不同开始和结束日期的每一行来执行它,然后将其折叠回每日级别。

mydata$subt <- as.numeric(as.Date(mydata$end, "%Y/%m/%d") - as.Date(mydata$start, "%Y/%m/%d") + 1)

require(data.table) 
mydata <- setDT(mydata)[ , list(idnum = id, date = seq(start, end, by = "day"), a=a/subt, b=b/subt), by = 1:nrow(mydata)]
mydata

   nrow idnum       date   a  b
1:    1     1 2010-01-01 140 48
2:    2     2 2010-01-01 150  5
3:    2     2 2010-01-02 150  5
4:    2     2 2010-01-03 150  5
5:    2     2 2010-01-04 150  5
6:    2     2 2010-01-05 150  5
7:    3     3 2010-01-02  28 18
8:    3     3 2010-01-03  28 18

mydata %>%
  group_by(date) %>%
  summarize(a = sum(a),
            b = sum(b))

期望的结果:

  date           a     b
  <date>     <dbl> <dbl>
1 2010-01-01   290    53
2 2010-01-02   178    23
3 2010-01-03   178    23
4 2010-01-04   150     5
5 2010-01-05   150     5

但是,我有很多行的开始日期和结束日期不同,有时差异的长度很长。我想知道是否有更简单的方法(即不展开每一行)来查找每个变量的日平均值。如果有一种方法可以在不首先找到每日数据的情况下找到每周平均值,那就太好了。谢谢!

这是 tidyverse 的选项。我们将 'start' 'end' 列转换为 Date class 和 ymd(来自 lubridate),创建 seq 日期从 'start' 到 'end' 与 map2mutate 和 'a'、'b' 对应的元素除以 lengths list 列 'date'、unnest 'date' 并按 'date' 分组,我们得到 'a'、[=29 的 sum =]

library(dplyr)
library(tidyr)
library(lubridate)
library(purrr)
mydata %>%
     mutate(across(c(start, end), ymd)) %>% 
     transmute(id, date = map2(start, end, seq, by = 'day'), a, b) %>% 
     mutate(across(c(a, b), ~ ./lengths(date)))  %>%
     unnest(date) %>%
     group_by(date) %>% 
     summarise(across(c(a, b), sum, na.rm = TRUE))
# A tibble: 5 x 3
#  date           a     b
#  <date>     <dbl> <dbl>
#1 2010-01-01   290    53
#2 2010-01-02   178    23
#3 2010-01-03   178    23
#4 2010-01-04   150     5
#5 2010-01-05   150     5