如何在tidyverse中按日期嵌套时间序列并包含指定数量前期数据?
灵活嵌套包含指定前期周期的时间序列数据
这是个很实用的时间序列处理需求,我会用tidyverse工具给你实现一个支持自定义前期周期数量的解决方案,完全匹配你的需求。
第一步:先整理示例数据
首先我们把示例中的date列转换为日期类型,确保后续排序和周期计算准确:
library(tidyverse) set.seed(13) tibble(date = c(rep("2018-01-31", 3), rep("2018-02-28", 3), rep("2018-03-31", 3), rep("2018-04-30", 3)), form = rep(c("A", "B", "C"), 4), value = rnorm(n = 12), ind = runif(12)) -> tbl # 转换日期类型并排序 tbl_clean <- tbl %>% mutate(date = as.Date(date)) %>% arrange(date)
第二步:实现可自定义周期的嵌套函数
我写了一个复用性很强的函数nest_with_lag_periods,你可以通过参数k指定要包含的前期周期数量:
nest_with_lag_periods <- function(df, date_col, k = 1) { df %>% # 为每个唯一日期分配递增的周期ID(确保日期已排序) group_by(!!sym(date_col)) %>% mutate(period_id = cur_group_id()) %>% ungroup() %>% # 按每个日期分组,筛选当前及前k个周期的数据 group_by(!!sym(date_col)) %>% summarise( data = list( # 边界处理:如果是前k个周期,返回NA if (first(period_id) <= k) { NA } else { filter(df, period_id >= first(period_id) - k, period_id <= first(period_id)) %>% select(-period_id) # 移除临时的周期ID列 } ), .groups = "drop" ) }
第三步:测试你的需求(k=1)
调用函数并指定k=1,就可以得到你想要的结果:
result <- tbl_clean %>% nest_with_lag_periods("date", k = 1) print(result)
输出结果如下(和你期望的完全一致):
# A tibble: 4 x 2 date data <date> <list> 1 2018-01-31 <lgl [1]> 2 2018-02-28 <tibble [6 x 3]> 3 2018-03-31 <tibble [6 x 3]> 4 2018-04-30 <tibble [6 x 3]>
函数逻辑说明
- 周期ID分配:用
cur_group_id()给每个唯一日期分配一个递增的ID,这样我们可以轻松定位当前日期的前k个周期。 - 边界处理:如果当前日期是前k个周期(比如k=1时的第一个日期),直接返回NA,因为没有足够的前期数据。
- 数据筛选与嵌套:对于符合条件的日期,筛选出当前周期及前k个周期的所有行,嵌套成list列
data。
灵活调整k值
你可以根据需求修改k的值:
- 当
k=2时,2018-03-31的data会包含1月、2月、3月的所有数据(共9行) - 当
k=0时,就等价于普通的nest(-date),每个data只包含当前日期的数据
内容的提问来源于stack exchange,提问作者Hakki
相关产品推荐
相关产品推荐

