R-跨年的累计和

时间:2020-11-03 15:08:17

标签: r data.table cumulative-sum

我有一个每日降水量测量数据表,如下所示:

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月之间的时间段。

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

如何实现?

2 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:2)

4月底是从年初开始的120天。如果您从date列中的所有条目中减去120天来创建pseudodate列,则生长期中每一天的pseudodate都将转移到上一年。由于从9月1日起减去120天即为同年5月4日,因此5月4日之前的任何pseudodate都将处于非增长期,并且该日期或之后的任何年份都必须在该年末。从该年9月开始的生长期。通过这种方法,我们可以根据每个实际日期是否在生长期以及生长期开始的年份来轻松标记。

然后,我们需要做的是过滤掉不在生长期的日期(group_by,在生长期开始的那一年),然后在cumsum列上执行precip

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日开始,因此我们已经错过了该季节的几个月生长期,因此,如果第一年也从1月开始,则可能需要从实际数据中删除第一年。

相关问题