为什么对数据帧进行子集化会改变时间序列的 class?

Why does subsetting a dataframe changes class of time series?

我有一个这样的数据框:

some_ts <- ts(1:12, frequency= 12, start= c(2020, 1))
as_df <- data.frame(time= time(some_ts), val= as.matrix(some_ts))
str(as_df)
'data.frame':   12 obs. of  2 variables:
 $ time: Time-Series  from 2020 to 2021: 2020 2020 2020 2020 2020 ...
 $ val : int  1 2 3 4 5 6 7 8 9 10 ...

这里一切正常。但是一旦我对数据进行子集化,时间序列的 class 就会发生变化:

as_df <- as_df[as_df$val != 4, ]
str(as_df)
'data.frame':   11 obs. of  2 variables:
 $ time: num  2020 2020 2020 2020 2020 ...
 $ val : int  1 2 3 5 6 7 8 9 10 11 ...

如何在不更改 class 的情况下对数据进行子集化?

可以 over-ride ts 子集函数的默认行为,即函数 stats:::'[.ts'。如果您改为定义以下函数:

`[.ts` <- function (x, i, j, drop = TRUE) 
{
  y <- as.numeric(x)
  if (missing(i)) return(x)
  if (missing(j)) y <- y[i] else y <- y[i, j]
  
  ts(y, start = start(x), frequency = frequency(x))

}

然后对时间序列进行子集化将得到时间序列:

df <- data.frame(a= 1:3, b= ts(1:3))

df$b[df$a != 2]
#> Time Series:
#> Start = 1 
#> End = 2 
#> Frequency = 1 
#> [1] 1 3

但也许现在您会明白为什么对时间序列进行子集化可能不是一个好主意,以及为什么作者决定在子集化时删除 class。时间序列保留了它的频率但缩短了它的长度,因此缩短了它的表观持续时间,这可能不是你想要的。值 3 的隐含日期是什么?

用户打算在此处发生的事情会产生太多歧义。你想让频率下降吗?要在缺失的月份中插入 NA 个值?如果子集是不规则的或随机的怎么办?时间序列看起来如何?

我想如果我设计这个 class 我可能也会谨慎行事并放弃 class 类型。也许你能看到更好的设计?