R:合并两个不规则时间序列
Posted
技术标签:
【中文标题】R:合并两个不规则时间序列【英文标题】:R: merge two irregular time series 【发布时间】:2011-10-28 16:49:32 【问题描述】:我有两个多元时间序列 x 和 y,它们都覆盖了大致相同的时间范围(一个比另一个早两年开始,但它们在同一日期结束)。两个系列都缺少日期列旁边的空列形式的观察结果,并且从某种意义上说,其中一个系列有多个日期在另一个系列中找不到,反之亦然。
我想创建一个数据框(或类似的),其中的一列列出了在 x 或 y 中找到的所有日期,没有重复的日期。对于每个日期(行),我想将 x 的观察值水平堆叠到 y 的观察值旁边,NA 填充缺失的单元格。示例:
>x
"1987-01-01" 7.1 NA 3
"1987-01-02" 5.2 5 2
"1987-01-06" 2.3 NA 9
>y
"1987-01-01" 55.3 66 45
"1987-01-03" 77.3 87 34
# result I would like
"1987-01-01" 7.1 NA 3 55.3 66 45
"1987-01-02" 5.2 5 2 NA NA NA
"1987-01-03" NA NA NA 77.3 87 34
"1987-01-06" 2.3 NA 9 NA NA NA
我尝试过的:使用 zoo 包,我尝试过 merge.zoo 方法,但这似乎只是将两个系列彼此相邻堆叠,日期(作为数字,例如“1987-01- 02" 显示为 6210),每个系列出现在两个单独的列中。
我已经坐了几个小时几乎一无所获,因此感谢所有帮助。
编辑:根据 Soumendra 的建议,下面包含一些代码
atcoa <- read.csv(file = "ATCOA_full_adj.csv", header = TRUE)
atcob <- read.csv(file = "ATCOB_full_adj.csv", header = TRUE)
atcoa$date <- as.Date(atcoa$date)
atcob$date <- as.Date(atcob$date)
# only number of observations and the observations themselves differ
>str(atcoa)
'data.frame': 6151 obs. of 8 variables:
$ date :Class 'Date' num [1:6151] 6210 6213 6215 6216 6217 ...
$ max : num 4.31 4.33 4.38 4.18 4.13 4.05 4.08 4.05 4.08 4.1 ...
$ min : num 4.28 4.31 4.28 4.13 4.05 3.95 3.97 3.95 4 4.02 ...
$ close : num 4.31 4.33 4.31 4.15 4.1 3.97 4 3.97 4.08 4.02 ...
$ avg : num NA NA NA NA NA NA NA NA NA NA ...
$ tot.vol : int 877733 89724 889437 1927113 3050611 846525 1782774 1497998 2504466 5636999 ...
$ turnover : num 3762300 388900 3835900 8015900 12468100 ...
$ transactions: int 12 9 24 17 31 26 34 35 37 33 ...
>atcoa[1:1, ]
date a.max a.min a.close a.avg a.tot.vol a.turnover a.transactions
1 1987-01-02 4.31 4.28 4.31 NA 877733 3762300 12
# using timeSeries package
ts.atcoa <- timeSeries::as.timeSeries(atcoa, format = "%Y-%m-%d")
ts.atcob <- timeSeries::as.timeSeries(atcob, format = "%Y-%m-%d")
>str(ts.atcoa)
Time Series:
Name: object
Data Matrix:
Dimension: 6151 7
Column Names: a.max a.min a.close a.avg a.tot.vol a.turnover a.transactions
Row Names: 1970-01-01 01:43:30 ... 1970-01-01 04:12:35
Positions:
Start: 1970-01-01 01:43:30
End: 1970-01-01 04:12:35
With:
Format: %Y-%m-%d %H:%M:%S
FinCenter: GMT
Units: a.max a.min a.close a.avg a.tot.vol a.turnover a.transactions
Title: Time Series Object
Documentation: Wed Aug 17 13:00:50 2011
>ts.atcoa[1:1, ]
GMT
a.max a.min a.close a.avg a.tot.vol a.turnover a.transactions
1970-01-01 01:43:30 4.31 4.28 4.31 NA 877733 3762300 12
# The following will create an object of class "data frame" and mode "list", which contains observations for the days mutual for the two series
>ts.atco <- timeSeries::merge(atcoa, atcob) # produces same result as base::merge, apparently
>ts.atco[1:1, ]
date a.max a.min a.close a.avg a.tot.vol a.turnover a.transactions b.max b.min b.close b.avg b.tot.vol b.turnover b.transactions
1 1989-08-25 7.92 7.77 7.79 NA 269172 2119400 19 7.69 7.56 7.64 NA 81176693 593858000 12
编辑:通过(使用 zoo 包)解决的问题
atcoa <- read.zoo(read.csv(file = "ATCOA_full_adj.csv", header = TRUE))
atcob <- read.zoo(read.csv(file = "ATCOB_full_adj.csv", header = TRUE))
names(atcoa) <- c("a.max", "a.min", "a.close",
"a.avg", "a.tot.vol", "a.turnover", "a.transactions")
names(atcob) <- c("b.max", "b.min", "b.close",
"b.avg", "b.tot.vol", "b.turnover", "b.transactions")
atco <- merge.zoo(atcoa, atcob)
感谢大家的帮助。
【问题讨论】:
您没有展示您实际尝试过的内容,但merge.zoo
肯定不只是堆叠动物园对象。 merge.zoo
上有一个帮助页面,其中包括文档和许多示例:?merge.zoo
。 zoo 附带的 5 个小插图(pdf 文档)提供了额外的文档和示例。有关更多信息,请参阅下面的帖子。
建议你这样做:nms <- c("", "max", "min", "close", "avg", "tot.vol", "turnover", "transactions"); atcoa <- read.zoo("ATCOA_full_adj.dat", header = TRUE, col.names = paste("a", nms, sep = "."))
。此外,由于这似乎不是一个 csv 文件,即字段没有用逗号分隔,因此在命名文件时最好不要使用 csv 作为扩展名。
【参考方案1】:
试试这个:
Lines.x <- '"1987-01-01" 7.1 NA 3
"1987-01-02" 5.2 5 2
"1987-01-06" 2.3 NA 9'
Lines.y <- '"1987-01-01" 55.3 66 45
"1987-01-03" 77.3 87 34'
library(zoo)
# in reality x might be in a file and might be read via: x <- read.zoo("x.dat")
# ditto for y. See ?read.zoo and the zoo-read vignette if you need other args too
x <- read.zoo(text = Lines.x)
y <- read.zoo(text = Lines.y)
merge(x, y)
给予:
V2.x V3.x V4.x V2.y V3.y V4.y
1987-01-01 7.1 NA 3 55.3 66 45
1987-01-02 5.2 5 2 NA NA NA
1987-01-03 NA NA NA 77.3 87 34
1987-01-06 2.3 NA 9 NA NA NA
【讨论】:
对于 Lines.x 和 Lines.y,你的意思是这些应该手动输入吗?数据集太大了... 我认为上述答案的 cmets 建议您使用 read.zoo 读取文件。 x 啊,你是对的。这解决了问题;我会更新帖子原帖。 如果您使用的是 read.zoo,则不需要使用 read.csv,因为它们都在下面使用 read.table。你可以只写 read.zoo("ATCOA_full_adj.csv", header=T)。 HTH【参考方案2】:您可以根据您的日期创建一个 timeSeries(timeSeries 库)对象,将它们合并(timeSeries 默认合并行为与 zoo 和 xts 不同,并且完全按照您的要求进行操作),然后从结果中生成 zoo/xts 对象以防您不想留在 timeSeries。
一种快速测试方法如下,假设您有两个动物园对象 zz1 和 zz2 -
library(timeSeries)
as.zoo(merge(as.timeSeries(zz1), as.timeSeries(zz2)))
将上述命令的输出与
进行比较merge(zz1, zz2)
你也可以cbind -
cbind(zz1, zz2)
前提是没有同名的共享列。即使有这样的列,你也可以选择你cbind的列,你会得到一个zoo对象。
cbind(zz1[, 1:2], zz2[, 2:3]) #Assuming other columns are common
【讨论】:
谢谢。当我尝试您的方法时,我注意到以下情况:当我在日期格式为“%Y-%m-%d”的数据框中使用 as.timeSeries 时,创建的 timeSeries 对象将具有日期格式“%Y- %m-%d %H:%M:%S";我在函数中指定 format="%Y-%m-%d" 似乎被忽略了。如果我然后合并(使用 base::merge 或 timeSeries::merge)两个这样的 timeSeries 对象,我会得到一个数据框,其日期格式为“%Y-%m-%d”,其中仅包含以下日期对两个对象是相互的。但是,这些列包含我想要的信息(如示例中所示)。有什么办法吗? 代码已包含在原帖中。as.zoo(merge(as.timeSeries(zz1), as.timeSeries(zz2)))
和 merge(as.timeSeries(zz1), as.timeSeries(zz2))
之间有什么区别?我喜欢你的回答。【参考方案3】:
在这里,我从 stat.ethz.ch 找到了一个更通用的方法
a <- ts(1:10, start=c(2014,6), frequency=12)
b <- ts(1:12, start=c(2015,1), frequency=12)
library(zoo)
m <- merge(a = as.zoo(a), b = as.zoo(b))
返回一个 ts 对象:
as.ts(m)
【讨论】:
第 5 行末尾的“m”是错字吗?【参考方案4】:这个怎么样:
## Generate unique sorted time values.
i <- sort(unique(c(index(x), index(y))))
## Empty data matrix.
v <- matrix(nrow=length(i), ncol=6, NA)
## Pull in data items.
v[match(index(x), i), 1:3] <- coredata(x)
v[match(index(y), i), 4:6] <- coredata(y)
## Build new zoo object.
d <- zoo(v, order.by=i)
【讨论】:
你可能会在这里做一些修改:如果我在分配给 i 时跳过 index(x) 和 index(y),我将得到一个唯一日期的向量(如果我只需使用索引,它不会起作用,因为它们在两个对象之间不相关 - 我必须比较日期)。我可以使用它来填充矩阵的第一列,就像你建议的那样。但是,我不确定“拉入数据项”阶段是否仍然有效:相反,我应该将 x 和 y 的日期列与矩阵的第一列进行比较,并在其中任何一个匹配时分配元素。以上是关于R:合并两个不规则时间序列的主要内容,如果未能解决你的问题,请参考以下文章