我在R中遇到stl()时间序列分解函数的问题,告诉我我的ts对象实际上并不是单变量的吗?
tsData <- ts(data = dummyData, start = c(2012,1), end = c(2014,12), frequency = 12)
> tsData
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
2012 22 26 34 33 40 39 39 45 50 58 64 78
2013 51 60 80 80 93 100 96 108 111 119 140 164
2014 103 112 154 135 156 170 146 156 166 176 193 204
> class(tsData)
[1] "ts"
> stl(tsData, s.window = "periodic")
Error in stl(tsData, s.window = "periodic") :
only univariate series are allowed
> dput(dummyData)
structure(list(index = c(22L, 26L, 34L, 33L, 40L, 39L, 39L, 45L,
50L, 58L, 64L, 78L, 51L, 60L, 80L, 80L, 93L, 100L, 96L, 108L,
111L, 119L, 140L, 164L, 103L, 112L, 154L, 135L, 156L, 170L, 146L,
156L, 166L, 176L, 193L, 204L)), .Names = "index", class = "data.frame", row.names = c(NA,
-36L))
任何人都知道如何解决这个问题?
答案 0 :(得分:9)
为了避免这些问题或错误,尝试通过形成原始数据点或值来制作单变量时间序列,调用ts()函数。
更好地说,您应该始终只将变量的值放在变量的整个结构中。让我通过一个非常简单的例子来解释一下:
想象一下,你有一个变量X,它是一个向量(很可能是从其他数据源导入或形成的)100x1维度,即它包含100个值或数据点。如果你想用这个向量制作一个单变量的时间序列,那么错误的方法就像你为你的情况做的那样:
ts(X,频率= 24)
要小心,正确的方法就是这样:
ts(X [1:100],频率= 24)
甚至是这样:
ts(X [1:100,1],频率= 24)
我希望亲爱的朋友,下次你需要制作一个单变量的时间序列时,你可以避免它。!!
答案 1 :(得分:5)
我不能100%确定问题的确切原因,但您可以通过将dummyData$index
传递给ts
而不是整个对象来解决此问题:
tsData2 <- ts(
data=dummyData$index,
start = c(2012,1),
end = c(2014,12),
frequency = 12)
##
R> stl(tsData2, s.window="periodic")
Call:
stl(x = tsData2, s.window = "periodic")
Components
seasonal trend remainder
Jan 2012 -24.0219753 36.19189 9.8300831
Feb 2012 -20.2516062 37.82808 8.4235219
Mar 2012 -0.4812396 39.46428 -4.9830367
Apr 2012 -10.1034302 41.32047 1.7829612
May 2012 0.6077088 43.17666 -3.7843705
Jun 2012 4.4723800 45.22411 -10.6964877
Jul 2012 -7.6629462 47.27155 -0.6086074
Aug 2012 -1.0551286 49.50673 -3.4516016
Sep 2012 2.2193527 51.74191 -3.9612597
Oct 2012 7.3239448 55.27391 -4.5978509
Nov 2012 18.4285405 58.80591 -13.2344456
Dec 2012 30.5244146 63.70105 -16.2254684
...
我猜测当你将data.frame
传递给data
的{{1}}参数时,一些额外的属性会继续存在,虽然这通常不会出现成为许多函数的问题,这些函数采用ts
类对象(单变量或其他),显然这是ts
的问题。
stl
修改:
进一步研究这个问题,我认为问题与R> all.equal(tsData2,tsData)
[1] "Attributes: < Names: 1 string mismatch >"
[2] "Attributes: < Length mismatch: comparison on first 2 components >"
[3] "Attributes: < Component 2: Numeric: lengths (3, 2) differ >"
##
R> str(tsData2)
Time-Series [1:36] from 2012 to 2015: 22 26 34 33 40 39 39 45 50 58 ...
##
R> str(tsData)
'ts' int [1:36, 1] 22 26 34 33 40 39 39 45 50 58 ...
- attr(*, "dimnames")=List of 2
..$ : NULL
..$ : chr "index"
- attr(*, "tsp")= num [1:3] 2012 2015 12
属性在dimnames
整体传递时有关。请注意dummyData
:
stl
以及if (is.matrix(x))
stop("only univariate series are allowed")
的定义:
如果x是一个向量并且有一个&#34; dim&#34;is.matrix返回TRUE。的属性 长度为2)否则为FALSE
所以虽然你传递matrix
单变量时间序列(原始stl
),但就函数而言,一个长度为2 tsData
属性的向量(即dimnames
)不是一个单变量系列。以这种方式进行错误处理似乎有点奇怪,但我确信该函数的作者有一个很好的理由。
答案 2 :(得分:1)
我遇到了同样的问题,这就是我如何解决的问题:
stl(x[,1], s.window = "periodic"
答案 3 :(得分:0)
我有同样的错误,事实上,正如nrussell所提到的,问题是我传递的时间序列也是一个矩阵。
(但是,$ index的东西对我来说不起作用,R抱怨说ts对象必须有一个或多个观察。我在R上相当新,并且不知道为什么会这样,但对于我采用以下方法)
您可以通过以下方式解决此问题:
dummyVector = as.vector(t(dummyData))
然后继续获取stl:
tsData = ts(dummyVector, start=2012, end=(2014, 12), frequency = 12)
stl = stl(tsData, "periodic")
如果您使用R Studio,您现在可以看到,您的时间序列列在
下2012年至2015年的时间序列[1:36]:yourData
之前,它很可能被列为
int [1:3,1:12] yourData
答案 4 :(得分:0)
问题可能是你没有指定end = c(yyyy,mm)。
如果您使用的是分解,则无需指定end =。如果要切换到stl并使用一些旧代码,则需要添加此参数(如果您没有使用它进行分解)。
这为我解决了“单变量”错误问题。
答案 5 :(得分:0)
解决时间序列数据问题的另一种方法是:
stl(tsData[, 1], s.window = "periodic")
请比较
str(tsData)
与
str(tsData[, 1])
看到差异。
答案 6 :(得分:0)
当数据框对象传递给 ts(
) 函数时,它将通过 data.matrix()
强制转换为数字矩阵(参见 help(ts)
)。
ts()
函数将返回一个 Time-Series 对象,该对象将是一个类 'ts' 的矩阵,具有一个新属性 'tsp' 和原始数据框属性。这些 lasts 被转换为 'dimnames' 作为 2 个属性的列表:dimnames[[1]]
(原为 'row.names')和 dimnames[[2]]
(原为 'names')。
当向量传递给 ts()
时,它将返回一个由向量和 'tsp' 属性组成的时间序列对象。
最后,当一个时间序列对象被传递给 stl()
时,它会通过 is-matrix() 检查天气对象是否是一个矩阵,如果为真则返回一个错误。
if (is.matrix(x))
stop("only univariate series are allowed")
注意:
help(ts)
)。要检查 R 对象的属性,请调用函数:attributes(obj)
还可以使用函数 is.vector(obj)
、dim(obj)
和 dimnames(obj)
来验证对象维度,即,如果它是向量。
参见下面的代码示例:
# Exploring stl() arguments #
# load packages ####
if (!require("pacman")) install.packages("pacman")
pacman::p_load("vctrs")
pacman::p_load("stats")
# create a data frame "df" ####
df <- vctrs::data_frame(x = 133:165, y = pi, z = seq(25.25, 1.25, by = -0.75))
# visualizing and checking attributes
head(df)
str(df)
attributes(df)
dimnames(df)
# accessing single vectors/variables with subsetting ####
# 1 - double brackets
head(df[[3]]) # return a vector
is.vector(df[[3]])
# 2 - $ operator
head(df$z) # returns a vector
is.vector(df$z)
# 3 - single brackets
head(df[3]) # return a data frame!
is.vector(df[3])
dim(df[3])
dimnames(df[3])
attributes(df[3])
# creating a Time-Series object using ts() ####
MySeriesTs1 <- ts(df[[3]], start = c(1999, 10), frequency = 12)
MySeriesTs1
str(MySeriesTs1)
dim(MySeriesTs1) # time-series is a vector
MySeriesTs2 <- ts(df$z, start = c(1999, 10), frequency = 12)
MySeriesTs2
str(MySeriesTs2)
dim(MySeriesTs2) # time-series is a vector
MySeriesTs3 <- ts(df[3], start = c(1999, 10), frequency = 12)
MySeriesTs3
str(MySeriesTs3)
dim(MySeriesTs3) # time-series is a matrix!
dimnames(MySeriesTs3)
attributes(MySeriesTs3)
# Note: ts() accepts either a vector, a matrix or a data frame object as argument.
# here I pass the data frame with all three variables as argument to ts()
MySeriesTs <- ts(df, start = c(1999, 10), frequency = 12)
MySeriesTs
dim(MySeriesTs)
str(MySeriesTs) #returns a matrix with a List of 2 "dimnames" attributes: NULL and "x" "y" "z"
# calling stl() function ####
# stl() accepts only univariate time series as argument.
# Therefore, if the Time-Series object is a matrix, it has to be subset when passed to stl.
# passing a vector
MyDecompose1 <- stl(MySeriesTs1, s.window = 'p') # RUN
# passing a vector
MyDecompose2 <- stl(MySeriesTs2, s.window = 'p') # RUN
# passing a matrix
MyDecompose3 <- stl(MySeriesTs3, s.window = 'p') # ERROR!
# passing a subset of a matrix
MyDecompose3 <- stl(MySeriesTs3[,"z"], s.window = 'p') # RUN
# passing a matrix
MyDecompose <- stl(MySeriesTs, s.window = 'p') #ERROR!
# passing a subset of a matrix
MyDecompose <- stl(MySeriesTs[,"z"], s.window = 'p') #RUN