You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言中如何将聚合层级时间序列转换为hts对象?

构建层级时间序列(hts)对象的实用解决方案

我来帮你搞定这个hts对象构建的问题——其实核心是把你的长格式层级数据转成符合hts要求的结构,再动态生成所需参数,不用硬编码适配可变的类别数量。

步骤1:把长格式数据转成宽格式

hts要求每个层级组合对应时间序列的一列,所以首先得把你的长表转成宽表,缺失的时间-层级组合用0填充:

library(tidyr)
library(hts)

# 假设你的原始数据框名为df
df_wide <- df %>%
  pivot_wider(
    names_from = c(level1, level2), 
    values_from = n, 
    values_fill = 0  # 填充没有数据的组合为0
  )

步骤2:动态生成nodes参数

nodes参数用来定义层级结构,是一个列表:第一个元素是顶层(level1)的类别数量,第二个元素是每个顶层类别对应的底层(level2)类别数量。我们可以从数据里动态计算,不用手动写死:

# 计算每个level1对应的level2唯一值数量
level2_counts <- df %>%
  dplyr::group_by(level1) %>%
  dplyr::summarise(count = dplyr::n_distinct(level2)) %>%
  dplyr::pull(count)

# 生成nodes列表
nodes <- list(
  length(unique(df$level1)),  # level1的类别总数
  level2_counts               # 每个level1下的level2数量
)

比如你的数据里,level1有A、B两个类别,A对应1个level2,B对应3个,所以nodes会自动生成list(2, c(1,3)),完美适配数据变化。

步骤3:转换为时间序列对象

注意小时级别的时间序列,frequency参数设为24(每天24小时)更合理,同时要指定起始时间:

# 提取起始时间的年、月、日、小时
start_time <- min(df$TIME)
start_params <- c(lubridate::year(start_time), 
                  lubridate::month(start_time), 
                  lubridate::day(start_time), 
                  lubridate::hour(start_time))

# 转换为ts对象(去掉TIME列)
df_ts <- ts(
  data = df_wide[, -which(names(df_wide) == "TIME")],
  start = start_params,
  frequency = 24
)

步骤4:构建hts对象

最后用hts()函数组合起来,colnames直接用宽表的列名就可以(已经是level1_level2的格式,清晰明了):

hts_obj <- hts(df_ts, nodes = nodes)

额外注意事项

  • 如果你的时间序列有缺失的小时点,记得先补全时间序列(比如用tidyr::complete(TIME = seq(min(TIME), max(TIME), by = "hour"))),否则ts对象会不连续。
  • 如果你想自定义层级名称,可以修改宽表的列名,或者在hts()里用characters参数指定层级标签。

内容的提问来源于stack exchange,提问作者Praveen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 10:52:29