R - 跨年的累计和

R - Cumulative sum that crosses years

我有一个数据 table,每天的降水量测量值如下所示:

library(data.table)
pr <- data.table(date=seq(as.Date("2000-01-01"), as.Date("2004-12-31"), by="1 day"),
                 precip=runif(1827, 0, 20))
            date    precip
   1: 2000-01-01  8.390553
   2: 2000-01-02 11.753791
   3: 2000-01-03  1.346553
   4: 2000-01-04 15.130108
   5: 2000-01-05  2.027514
  ---                     
1823: 2004-12-27 17.550784
1824: 2004-12-28  7.054898
1825: 2004-12-29  4.458190
1826: 2004-12-30  6.989788
1827: 2004-12-31  2.257400

我想获得此数据集中所有生长季节的累积降水量,其中生长季节定义为 9 月到 4 月之间的时间段。

因此,结果数据 table 应包含 Sep2000 - Apr2001、Set2001 - Apr 2002 等的累计总和。

如何实现?

4 月底距年初还有 120 天。如果您从 date 列中的所有条目中减去 120 天以创建一个 pseudodate 列,那么您生长期中每一天的 pseudodate 将移至上一年。由于从 9 月 1 日减去 120 天得到同年 5 月 4 日,因此 5 月 4 日之前的任何 pseudodate 都将处于 non-growing 期间,并且该日期或之后直到年底的任何内容都必须是在当年九月开始的生长期。通过这种方法,我们可以很容易地根据是否处于生长期,并根据生长期开始的年份来标记每个实际日期。

然后我们需要做的就是过滤掉不在生长期的日期,group_by 生长期开始的那一年,然后在 [=17= 上执行 cumsum ] 专栏:

library(dplyr)
library(lubridate)

pr %>% mutate(pseudodate = date - days(120),
              is_growing = yday(pseudodate) > 125,
              season_beginning = year(pseudodate)) %>%
  filter(is_growing) %>%
  mutate(cum_precip = cumsum(precip)) %>%
  select(date, precip, season_beginning, cum_precip)

#>             date    precip season_beginning  cum_precip
#>    1: 2000-01-01 17.694152             1999    17.69415
#>    2: 2000-01-02  6.066319             1999    23.76047
#>    3: 2000-01-03  4.793192             1999    28.55366
#>    4: 2000-01-04 15.753112             1999    44.30678
#>    5: 2000-01-05 12.253172             1999    56.55995
#>   ---                                                  
#> 1198: 2004-12-27  8.983804             2004 11490.72677
#> 1199: 2004-12-28  6.740315             2004 11497.46709
#> 1200: 2004-12-29  3.899960             2004 11501.36705
#> 1201: 2004-12-30  6.357432             2004 11507.72448
#> 1202: 2004-12-31  3.950666             2004 11511.67515

当然,由于这个示例数据集从 1 月 1 日开始,我们已经错过了那个季节的几个月的生长期,所以如果第一年也开始于一月.

这是一个data.table方法。我们首先确定生长 (TRUE) / 收获 (FALSE) 季节,然后给每个季节一个 run-length id,最后按季节计数总结开始和结束日期以及总降水量。

set.seed(1)
pr <- data.table(
  date=seq(as.Date("2000-01-01"), as.Date("2004-12-31"), by="1 day"),
  precip=runif(1827, 0, 20)
)

pr[
  , gr_season := !(month(date) %in% 5:8)
][
  , season_count := rleidv(gr_season) 
][
  gr_season == TRUE, .(period = paste0(head(date, 1L), "/", tail(date, 1L)), precip = sum(precip)), 
  by = season_count
]

输出

   season_count                period   precip
1:            1 2000-01-01/2000-04-30 1251.741
2:            3 2000-09-01/2001-04-30 2352.559
3:            5 2001-09-01/2002-04-30 2466.817
4:            7 2002-09-01/2003-04-30 2326.178
5:            9 2003-09-01/2004-04-30 2418.478
6:           11 2004-09-01/2004-12-31 1136.972

生长季节的每日累积量

pr[
  , gr_season := !(month(date) %in% 5:8)
][
  , season_count := rleidv(gr_season)
][
  gr_season == TRUE, .(date = date, precip = cumsum(precip)), 
  by = season_count
]

输出

      season_count       date      precip
   1:            1 2000-01-01    5.310173
   2:            1 2000-01-02   12.752651
   3:            1 2000-01-03   24.209719
   4:            1 2000-01-04   42.373874
   5:            1 2000-01-05   46.407513
  ---                                    
1208:           11 2004-12-27 1101.280221
1209:           11 2004-12-28 1112.926760
1210:           11 2004-12-29 1114.345408
1211:           11 2004-12-30 1125.758288
1212:           11 2004-12-31 1136.971833