【问题标题】:Excel or R: Preparing time series from multiple sources?Excel 或 R:从多个来源准备时间序列?
【发布时间】:2011-09-08 16:25:48
【问题描述】:

最近,我经常不得不在同一个分析中处理来自多个 .csv 源的时间序列数据。 为简单起见,我们假设所有系列都是常规的季度系列(两者之间没有缺失值)。通常,原始 .csv 数据包含一个日期列和 1-3 个变量。 不幸的是,该系列在 .csv 文件中的长度不相等。

我开始在 R 中组织我的数据集,结果发现一大堆包含大量window()commands。另外,我必须在将 NA 和原始系列转换为 ts()objects 之前将它们连接起来,因为我发现连接(多变量)ts()objects 非常违反直觉。 请注意,我添加 NA 的原因是我希望所有系列都具有相同的长度。当然,我可以修剪较长的,但是当不使用较短的系列时,我最终会失去观察。

我考虑编写一个函数来读取 .csv 文件并使用它的日期列来创建 ts()objects 并且可能与另一个函数合并所有单个系列以在数据丢失时创建一个包含 NA 的多元系列。我发现自己一直在切换数据类型,阅读 ts 和 zoo 手册——我简直不敢相信它有那么复杂。

我真的觉得这个问题真的很普遍,想到了在excel中的准备。我的意思是我真的很讨厌excel,但是这次我想知道更有经验的用户会做什么? R 还是 Excel?

编辑:添加了一些示例数据(需要汇总每日数据) 文件1:

27.05.11;5965.95
26.05.11;5947.06
25.05.11;5942.82
24.05.11;5939.98

file2(没有日期列,但我知道开始和频率)

Germany;Switzerland;USA;OECDEurope
69,90974;61,8241;55,60966;64,96157
67,0394;62,18966;56,47361;64,15152
70,56651;63,6347;56,87237;65,43568

文件3:

1984-04-01,33.3238396624473
1984-07-01,63.579833082501
1984-10-01,35.8375401560349

我承认示例性数据确实有助于说明问题,但它是解决比我更有经验的用户的问题的最佳实践类型。您如何为多变量 ts 分析准备数据?

【问题讨论】:

  • 我的意思是我确实明白,如果知道开始和频率,常规系列不需要日期列,但部分问题是:是否有创建 ts 或 @987654329 的标准方法@ 来自 csv 的带有日期列的对象?
  • 您可能需要提供一些数据文件示例,因为read.zoo 应该可以处理其中一些问题。

标签: r time-series


【解决方案1】:

我一直在 R 中这样做。您可能会发现在 Excel 中执行此操作更容易,但如果您的数据发生更改,您必须再次执行相同的过程。使用 R 可以更轻松地更新和重现结果。

使用 zoo 的 yearmonyearqtr 索引类,处理每月或每季度的频率变得更加容易。一旦您将数据放入具有 yearqtr 索引的 zoo 对象中,您所要做的就是合并所有对象。

这是您的示例数据:

Lines1 <-
"27.05.11;5965.95
26.05.11;5947.06
25.05.11;5942.82
24.05.11;5939.98"
f1 <- read.csv2(con <- textConnection(Lines1), header=FALSE)
close(con)

Lines2 <-
"Germany;Switzerland;USA;OECDEurope
69,90974;61,8241;55,60966;64,96157
67,0394;62,18966;56,47361;64,15152
70,56651;63,6347;56,87237;65,43568"
f2 <- read.csv2(con <- textConnection(Lines2), header=TRUE)
close(con)

Lines3 <-
"1984-04-01,33.3238396624473
1984-07-01,63.579833082501
1984-10-01,35.8375401560349"
f3 <- read.csv(con <- textConnection(Lines3), header=FALSE)
close(con)

以下示例假设第一个文件的开始日期是 1984Q2,第二个文件的开始日期是 1984Q4。您可以看到merge.zoo 负责为您对齐所有日期。在您的zoo 对象中的所有内容都对齐后,您可以使用as.ts 方法创建一个mts 对象。

z1 <- zoo(f1[,-1], as.Date(f1[,1], "%d.%m.%y"))
z2 <- zoo(f2, as.yearqtr("1984Q4")+(seq_len(NROW(f1))-1)/4)
z3 <- zoo(f3[,-1], as.yearqtr(as.Date(f3[,1])))

library(xts)
# Use xts::apply.quarterly to aggregate series with higher periodicity.
# Here I just take the last obs but you could use another function (e.g. mean).
z1 <- apply.quarterly(z1, last)
index(z1) <- as.yearqtr(index(z1))  # convert the index to yearqtr

(Z <- merge(z1,z2,z3))
#         z1      Germany  Switzerland USA      OECDEurope z3
# 1984 Q2 <NA>    <NA>     <NA>        <NA>     <NA>       33.32383
# 1984 Q3 <NA>    <NA>     <NA>        <NA>     <NA>       63.57983
# 1984 Q4 <NA>    69.90974 61.8241     55.60966 64.96157   35.83754
# 1985 Q1 <NA>    67.0394  62.18966    56.47361 64.15152   <NA>
# 1985 Q2 <NA>    70.56651 63.6347     56.87237 65.43568   <NA>
# 1985 Q3 <NA>    69.90974 61.8241     55.60966 64.96157   <NA>
# 2011 Q2 5965.95 <NA>     <NA>        <NA>     <NA>       <NA>

# Note that ts will create an object with a observation for every period,
# even if all the columns are missing.
TS <- as.ts(Z)

【讨论】:

  • +1 我会在 10 次中将 R 超过 Excel 10 次,但不知何故我在这里迷路了,失去了信心。心情又好了!谢谢。
  • 为了不丢失属性,您通常以什么格式保存生成的 mts?
  • 请注意,Joshua 的代码不会聚合第一个系列。第一列也是(每日)日期列——即使它是一种丑陋的欧元格式..
  • 糟糕,我以为所有系列都是季刊。我不知道您想要/需要汇总一些。请参阅我的编辑以了解如何执行此操作。
【解决方案2】:

我对这类问题的策略是:

  1. 将每个数据源读入标准data.frame
  2. 清理每个 data.frame,即将数据转换为所需格式、处理缺失值等。
  3. 合并或加入标准 data.frame
  4. 执行任何聚合数据清理,例如添加空行、删除重复项等。
  5. 然后才将数据传递到下一步,例如转换为ts对象,绘制它等。

使用您的示例数据:

v1 <- "27.05.11;5965.95
26.05.11;5947.06
25.05.11;5942.82
24.05.11;5939.98"

v2 <- "Germany;Switzerland;USA;OECDEurope
69,90974;61,8241;55,60966;64,96157
67,0394;62,18966;56,47361;64,15152
70,56651;63,6347;56,87237;65,43568"


v3 <- "1984-04-01,33.3238396624473
1984-07-01,63.579833082501
1984-10-01,35.8375401560349"

# Read and clean data
dat1 <- read.table(textConnection(v1), header=FALSE, sep=";", dec=".")
names(dat1) <- c("date", "V1")
dat1$date <- as.Date(dat1$date, format="%d.%m.%y")
dat1

dat2 <- read.table(textConnection(v2), header=TRUE, sep=";", dec=",")
dat2$date <- seq(as.Date("2011/1/1"), by="3 months", length.out=3)
dat2

dat3 <- read.table(textConnection(v3), header=FALSE, sep=",", dec=".")
names(dat3) <- c("date", "V2")
dat3$date <- as.Date(dat3$date)
dat3

# Merge separate data.frames.
# I use join() in package plyr, you may wish to use merge(), rbind.fill, etc
library(plyr)
join(join(dat1, dat2, type="full"), dat3, type="full")

结果:

         date      V1  Germany Switzerland      USA OECDEurope       V2
1  2011-05-27 5965.95       NA          NA       NA         NA       NA
2  2011-05-26 5947.06       NA          NA       NA         NA       NA
3  2011-05-25 5942.82       NA          NA       NA         NA       NA
4  2011-05-24 5939.98       NA          NA       NA         NA       NA
5  2011-01-01      NA 69.90974    61.82410 55.60966   64.96157       NA
6  2011-04-01      NA 67.03940    62.18966 56.47361   64.15152       NA
7  2011-07-01      NA 70.56651    63.63470 56.87237   65.43568       NA
8  1984-04-01      NA       NA          NA       NA         NA 33.32384
9  1984-07-01      NA       NA          NA       NA         NA 63.57983
10 1984-10-01      NA       NA          NA       NA         NA 35.83754

【讨论】:

    猜你喜欢
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-13
    • 2016-07-24
    • 2021-06-17
    • 1970-01-01
    相关资源
    最近更新 更多