我有一些高格式的(金融时间系列)数据:
require(data.table)
DT <- data.table(Variable=c(rep("a",times = 3), rep("b", times=3)),
Date=as.Date(c("2014-04-01","2014-04-02","2014-04-03"
,"2014-04-02", "2014-04-03","2014-04-04")),
Value=c(1:3,3:1), key=c("Variable","Date"))DT
Variable Date Value
1: a 2014-04-01 1
2: a 2014-04-02 2
3: a 2014-04-03 3
4: b 2014-04-02 3
5: b 2014-04-03 2
6: b 2014-04-04 1我想要计算第三个变量spread,其中每个公共Date行的spread = a - b (基本上是两个时间序列之间的差额--金融领域中的一个公共转换)。
期望输出:
Variable Date Value
1: spread 2014-04-02 -1
2: spread 2014-04-03 1当我将数据转换为宽格式(即包含列dcast.data.table的表)时,我知道有什么解决方案,但是由于大数据的性能问题,是否有一种优雅的方法可以使用a)dplyr和b)data.table (两部分问题)在高格式下直接实现?
理想情况下,在dplyr方面,我正在寻找像mutate(tbl_dt(DT, tall=TRUE), spread=a-b)这样有表现力的东西。(免责声明:我是dplyr__的新手)
真实生活数据集:
# download 200 stocks from Quandl.com. requires free registration
library(Quandl); library(data.table); library(plyr)
ntickers <- 200 ; auth.token="register_free_to_obtain_token"
code.file <- tempfile()
download.file("https://s3.amazonaws.com/quandl-static-content/quandl-stock-code-list.csv",
destfile=code.file)
tickers <- na.omit(read.csv2(code.file, sep=",", stringsAsFactors=FALSE)[,"Price.Code"])
lst <- na.omit(tickers)[1:ntickers]
names(lst) <- lst
Q <- ldply(lst, Quandl,
type = "raw", end_date="2014-04-08",
sort="asc", auth=auth.token) # might take minutes
DT <- as.data.table(Q)[,Date:=as.IDate(Date)]
setnames(DT, ".id", "Instrument")
setkey(DT, Instrument, Date)
> dim(DT); object.size(DT)
[1] 685512 8
41145752 bytes
> DT
Instrument Date Open High Low Close Volume Adjusted Close
1: GOOG/AMEX_ABI 1981-03-11 NA NA 6.56 6.75 217200 NA
2: GOOG/AMEX_ABI 1981-03-12 NA NA 6.66 6.88 616400 NA
3: GOOG/AMEX_ABI 1981-03-13 NA NA 6.81 6.84 462000 NA
4: GOOG/AMEX_ABI 1981-03-16 NA NA 6.81 7.00 306400 NA
5: GOOG/AMEX_ABI 1981-03-17 NA NA 6.88 6.88 925600 NA
---
685508: YAHOO/TSX_AHX_TO 2014-04-02 0.75 0.75 0.75 0.75 5000 0.75
685509: YAHOO/TSX_AHX_TO 2014-04-03 0.79 0.82 0.75 0.82 25700 0.82
685510: YAHOO/TSX_AHX_TO 2014-04-04 0.81 0.81 0.78 0.80 4500 0.80
685511: YAHOO/TSX_AHX_TO 2014-04-07 0.80 1.05 0.80 0.96 40400 0.96
685512: YAHOO/TSX_AHX_TO 2014-04-08 0.95 0.96 0.90 0.95 21300 0.95发布于 2014-04-08 02:11:10
你应该能够处理好这个问题:
> merge(DT["a", ], DT["b",], by="Date")
Date Variable.x Value.x Variable.y Value.y
1: 2014-04-02 a 2 b 3
2: 2014-04-03 a 3 b 2merge.data.table的帮助页建议您阅读FAQ 1.12来详细比较XY,.接近。
发布于 2014-04-08 14:27:51
下面是使用dplyr的一种方法。首先,我们创建数据:
require(dplyr)
df <- data.frame(
Variable = rep(c("a", "b"), each = 3),
Date = rep(as.Date("2014-04-01") + 0:2, 2),
Value = c(1:3, 3:1)
)我们可以使用矢量化的比较,而不是旋转成宽的形式:
df %.%
group_by(Date) %.%
summarise(spread = Value[Variable == "a"] - Value[Variable == "b"])
## Source: local data frame [3 x 2]
##
## Date spread
## 1 2014-04-01 -2
## 2 2014-04-02 0
## 3 2014-04-03 2如果存在多个a或b值,这将正确失败,因为summarise()要求结果的长度为1。同样的方法也适用于data.table,但是您需要在检查结果时更加小心(因为与dplyr相比,这里的数据表不那么严格/灵活)。
您还可以使用BondedDust建议的联接方法。对于dplyr,它不像使用data.table那样方便:
a <- df %.% filter(Variable == "a") %.% select(-Variable)
b <- df %.% filter(Variable == "b") %.% select(-Variable)
inner_join(a, b, by = "Date") %.%
mutate(spread = Value.x - Value.y)
## Date Value.x Value.y spread
## 1 2014-04-01 1 3 -2
## 2 2014-04-02 2 2 0
## 3 2014-04-03 3 1 2https://stackoverflow.com/questions/22924451
复制相似问题