使用dynlm与ts()进行时间序列回归遭遇zoo无效对象错误
问题
我的数据结构如下:
year <- c(rep(2001:2021,3)) industry <- c(rep("a",21),rep("b",21),rep("c",21)) value1 <- c(sample(1:300, 63)) value2 <- c(sample(1:300, 63)) df <- data.frame(year, industry, value1, value2)
尝试用以下代码做时间序列回归:
df_ts <- ts(df, start = 2001, end = 2021, frequency = 1) dynlm(d(value1) ~ time + L(value1, 1) + L(value2, 1) + d(L(value1, 1)) + d(L(value1, 2)) + d(L(value1, 3)) + d(L(value1, 4)) + d(L(value2, 1)) + d(L(value2, 2)) + d(L(value2, 3)) + d(L(value2, 4)), data=df_ts)
结果报错:
Error in zoo(structure(x, dim = dim(x)), index(x), ...) : “x” : attempt to define invalid zoo object
我已经用ts()把数据转成年度时间序列,搞不懂为啥会出现zoo相关的错误。怀疑过面板数据结构的问题,把数据按行业拆分后单独转成ts再运行,还是报同样的错,查了文档和资料也没解决,求帮忙排查。
解决方案
报错原因
ts()处理含非数值列的数据集会出问题:你的df里有字符串类型的industry列,用ts()转换时,非数值列会被强制转成因子,而dynlm底层依赖zoo对象处理时间序列,这种混合类型的ts对象无法被正确解析成合法的zoo对象,直接触发报错。- 拆分后序列长度不够支撑高阶滞后:单个行业的时间序列只有21个观测值,但你用到了
L(value1,4)这类4阶滞后项,加上差分操作后,有效样本量会大幅缩水,也可能触发内部处理错误。
修复方法
- 拆分面板数据时只保留数值列:按行业拆分后,剔除
industry列,只保留时间和数值列,再转换为ts对象:
library(dynlm) library(zoo) # 拆分数据,只保留需要的列 df_list <- split(df[, c("year", "value1", "value2")], df$industry) # 逐个处理每个行业的时间序列 lapply(df_list, function(sub_df) { # 仅将数值列转换为ts对象 sub_ts <- ts(sub_df[, c("value1", "value2")], start = 2001, frequency = 1) # 调整滞后项阶数(4阶滞后会让有效样本太少,改成3阶) model <- dynlm(d(value1) ~ time + L(value1, 1) + L(value2, 1) + d(L(value1, 1)) + d(L(value1, 2)) + d(L(value1, 3)) + d(L(value2, 1)) + d(L(value2, 2)) + d(L(value2, 3)), data = sub_ts) return(summary(model)) })
- 直接用zoo对象处理更稳妥:跳过
ts()转换,直接将子数据框转成zoo对象,避免ts类型转换的问题:
lapply(df_list, function(sub_df) { sub_zoo <- zoo(sub_df[, c("value1", "value2")], order.by = sub_df$year) model <- dynlm(d(value1) ~ time + L(value1, 1) + L(value2, 1) + d(L(value1, 1)) + d(L(value1, 2)) + d(L(value1, 3)), data = sub_zoo) return(summary(model)) })
- 注意滞后项阶数:21个观测值用4阶滞后的话,有效样本只剩17个,建议根据样本量调整滞后阶数,避免样本不足影响模型可靠性。
内容的提问来源于stack exchange,提问作者MaMö
相关产品推荐
相关产品推荐

