从带有时间戳的 csv 导入数据

Import data from csv with timestamps

我的 csv 文件如下所示:

A,A,B,B,C,C,… 
Timestamp,Price,Timestamp,Price,Timestamp,Price,…
6/1/15,20,6/1/15,97,6/1/15,279,… 
5/29/15,21,5/29/15,96,5/29/15,276,…

其中 A-C 是具有每日价格的股票。我想把它转换成这种形式,

            A   B   C
6/01/2015   20  97  279
5/29/2015   21  96  276
m/d/Y     price price price

首先我尝试使用 readSeries(file="name.csv", header=TRUE, sep=";", format="%d/%m/%Y") 但是我得到的日期和每只股票在单独列中的价格。看起来像这样

               A    A          B    B          C    C
[1,]    06/01/2015  20  06/01/2015  97  06/01/2015  279
[2,]    5/29/2015   21  5/29/2015   96  5/29/2015   276

我的第二次尝试是用 read.zoo(file="name.csv", sep=",", header=TRUE, index="Timestamp", format="%m/%d/%Y") 阅读它。这里我得到错误信息index has 6375 bad entries at data rows,但是格式是正确的。 我的问题是这两个应用函数中的哪一个更适合我的问题,我怎样才能达到我想要的输出?

也许这就足够了?

stocks="A,A,B,B,C,C
6/1/15,20,6/1/15,97,6/1/15,279
5/29/15,21,5/29/15,96,5/29/15,276
"
df = read.csv(text=stocks)
s = seq (2, ncol(df), by = 2)
idx = c(1, s)  # only want 1st column and stock price columns
df2 = df[,idx]
colnames(df2) = c("date", colnames(df)[s-1])

输出df2

     date  A  B   C
1  6/1/15 20 97 279
2 5/29/15 21 96 276

更新:

根据评论讨论,我用下面的代码替换了 colnames(df2)... 行,以便以正确的格式放置日期并将它们放在数据框的行名中。不幸的是,数据框的行名只能是字符向量,不能是日期格式。 (旁注:小心在数据框中使用行名:http://www.perfectlyrandom.org/2015/06/16/never-trust-the-row-names-of-a-dataframe-in-R/

rownames(df2) = strftime(as.Date(df2[,1], "%m/%d/%y"), format = "%m/%d/%Y")
df2[,1]=NULL
colnames(df2) = c(colnames(df)[s-1])

输出df2

            A  B   C
06/01/2015 20 97 279
05/29/2015 21 96 276

1)这里我们使用read.zoo。我们使用 textConnection(Lines)text=Lines 来保持这种自包含,但实际上用 file = "name.csv" 替换了每个。

首先我们计算给出 n 的字段。然后我们读入数据并指定 header、comma-separated 字段和日期格式。 (请注意,给定问题顶部显示的数据,格式应将年份指定为 %y 而不是问题中显示的 %Y。)输入的第二行以 T 开头所以指定 T 开始注释以有效地跳过该行。接下来我们指定 check.names=FALSE 以防止它混淆列名。最后,假设每行的日期相同,这样我们只需要每行的第一个日期。使用 colClasses 我们可以省略其他日期列,方法是指定它们属于 class NULL.

library(zoo)

Lines <- "A,A,B,B,C,C
Timestamp,Price,Timestamp,Price,Timestamp,Price
6/1/15,20,6/1/15,97,6/1/15,279
5/29/15,21,5/29/15,96,5/29/15,276"

n <- count.fields(textConnection(Lines), sep = ",")[1]
colClasses <- c("character", "numeric", rep(c("NULL", "numeric"), n/2-1))

read.zoo(text = Lines, header = TRUE, sep = ",", format = "%m/%d/%y",
 comment = "T",  check.names = FALSE, colClasses = colClasses)

这给出:

            A  B   C
2015-05-29 21 96 276
2015-06-01 20 97 279

如果可以硬编码字段的数量,我们可以通过省略 count.fields 语句并将 n/2-1 替换为 2 来略微减少代码。

1a) 如果 header 行中可以有 T,则使用此代替:

L <- readLines(textConnection(Lines))[-2]
read.zoo(text = L, header = TRUE, sep = ",", format = "%m/%d/%y", 
  check.names = FALSE, colClasses = colClasses)

2) 使用上面计算的 colClasses 的 base R 的替代方案是:

DF <- read.csv(text = Lines, comment = "T", check.names = FALSE, colClasses = colClasses)
DF[[1]] <- as.Date(DF[[1]], "%m/%d/%y")
names(DF)[1] <- "Date"

2a) 类似地,如果第一行可以包含 T 则使用此代替,其中 L 来自 (1a),colClasses 来自(1).

DF <- read.csv(text = L, check.names = FALSE, colClasses = colClasses)
DF[[1]] <- as.Date(DF[[1]], "%m/%d/%y")
names(DF)[1] <- "Date"