如何用zoo/xts将月度时序按自定义3月周期聚合为季度总和
解决xts月度数据按自定义3个月周期聚合为季度总和的问题
要实现以最后可用月份为结束的3个月期间的月度值求和,你可以手动生成分组端点,再结合period.apply完成聚合,具体步骤如下:
核心实现代码
library(xts) # 复现示例数据 months <- as.yearmon(c(paste0("2021-", 11:12), paste0("2022-", 1:10))) values <- c(23, 21, 45, 63, 12, 45, 23, 91, 28, 17, 27, 28) ts <- as.xts(values, order.by = months, dateFormat="yearmon") # 生成自定义分组端点:每3个月为一组,取每组最后一行的位置 n <- nrow(ts) custom_endpoints <- c(0, seq.int(3, n, by = 3)) # 执行聚合求和 result <- period.apply(ts, INDEX = custom_endpoints, FUN = sum) result
执行后输出与预期一致:
[,1] Jan 2022 89 Apr 2022 120 Jul 2022 142 Oct 2022 72
方法说明
- 自定义端点逻辑:你的数据是按时间升序排列的月度数据,每3行对应连续3个月的周期。通过
seq.int生成每组的结束位置(从第3行开始,每3行取一个端点),加上起始端点0,形成完整的分组边界。 - period.apply聚合:该函数会根据给定端点分割xts数据,对每个组应用
sum函数,最终结果的时间索引自动取每组最后一行的时间,正好满足“以最后可用月份为周期结束”的要求。
为什么之前的方法不适用
apply.quarterly严格按照日历季度(1-3月、4-6月等)分组,和自定义3个月周期逻辑不符。endpoints的on参数仅支持预设时间周期(如"months"、"quarters"等),无法直接指定"3 months",因此需要手动生成端点。
处理非整数倍的情况
如果数据行数不是3的整数倍,默认逻辑会把最后不足3个月的部分单独作为一组求和。若只想保留完整的3个月组,可修改端点生成逻辑:
# 仅保留完整的3个月组 full_groups_end <- n - (n %% 3) custom_endpoints <- c(0, seq.int(3, full_groups_end, by = 3)) result_full <- period.apply(ts, INDEX = custom_endpoints, FUN = sum)
内容的提问来源于stack exchange,提问作者Andrea M
相关产品推荐
相关产品推荐

