首页 > 解决方案 > 将数据帧转换为 R 中的 TS 对象

问题描述

我有一个看起来像这样的数据框:

  DAY     X1996 X1997 
1 1-Jul    98    86   
2 2-Jul    97    90   
3 3-Jul    97    93   
....

我想最终得到一个 TS 对象,这样我就可以对其进行 HoltWinters 平滑处理。我想我希望它看起来像这样(虽然我不确定,因为我以前没有做过 HoltWinters):

Day    Year   Temp
1-Jul  1996   98
2-Jul  1996   98
3-Jul  1996   98
...
1-Jul  1997   86
2-Jul  1997   90
3-Jul  1997   93

这就是我想要做的:

df <- read.delim("temps.txt")
myts <- as.ts(df)

但这看起来不像我需要做一个 Holtwinters 模型。我已经查看了 stackoverflow 以及 TS 和 Zoo 的文档,但我一直坚持如何创建这个 TS 对象。朝着正确的方向推动将不胜感激。

标签: rholtwinters

解决方案


ts 对象通常用于月度、季度或年度数据,而不是每日数据;但是,如果我们删除 2 月 29 日,那么我们可以创建一个 ts 对象,其时间是年份加上一个分数 0/365、1/365、...、364/365,如果没有丢失日期,它将有规律地间隔。关键是如果季节性是基于一年的,那么我们每年必须有相同数量的点才能将其表示为 ts 对象。

首先转换为具有普通日期的动物园对象 z0,删除给出 z 的 2 月 29 日,在动物园对象 zz 中创建上述时间索引,然后将其转换为 ts。

library(data.table)
library(lubridate)
library(zoo)

m <- melt(as.data.table(df), id.vars = 1)
z0 <- with(m, zoo(value, as.Date(paste(variable, DAY), "X%Y %d-%b")))
z <- z0[! (month(time(z)) == 2 & day(time(z)) == 29)]  

tt <- time(z)
zz <- zoo(coredata(z), year(tt) + (yday(tt) - ((month(tt) > 2) & leap_year(tt)) - 1)/365)
as.ts(zz)

在闰年删除 12 月 31 日

上面我们删除了闰年的 2 月 29 日,但另一种方法是删除闰年的 12 月 31 日,提供稍微简单的代码,从而避免使用leap_year,因为我们可以简单地删除 yday 为 366 的任何一天。z0 来自上方。

zz0 <- z0[yday(time(z0)) <= 365]
tt <- time(zz0)
zz <- zoo(coredata(zz0), year(tt) + (yday(tt) - 1) / 365)
as.ts(zz)

汇总到每月

另一种方法是将数据减少为月度数据。然后它相对简单,因为 ts 具有表示月度数据的工具。下面我们使用了每个月的最后一点,但如果需要,我们可以使用平均值或其他标量摘要。

ag <- aggregate(z0, as.yearmon, tail, 1)  # use last point in each month
as.ts(ag)

笔记

制成可重现形式的问题中的 df 如下(但是,我们需要用更多数据填写它以避免生成具有许多 NA 的 ts 对象)。

df <- structure(list(DAY = structure(1:3, .Label = c("1-Jul", "2-Jul", 
"3-Jul"), class = "factor"), X1996 = c(98L, 97L, 97L), X1997 = c(86L, 
90L, 93L)), class = "data.frame", row.names = c("1", "2", "3"
))

推荐阅读