我可以从名单列表中创建新的xts列吗?

时间:2015-01-06 00:20:43

标签: r xts

我的目标:从yahoo读取数据文件,然后使用列表对每个xts执行计算,以创建xts的名称和要分配结果的列的名称。

为什么呢?我想对大量xts数据集执行相同的计算,而不必重新键入单独的行以对每个数据集执行相同的计算。

首先,获取2个ETF的数据集:

library(quantmod)
# get ETF data sets for example
startDate = as.Date("2013-12-15") #Specify period of time we are interested in
endDate = as.Date("2013-12-31")
etfList <- c("IEF","SPY")
getSymbols(etfList, src = "yahoo", from = startDate, to = endDate)

为简化编码,请更换ETF。来自雅虎数据的前缀

colnames(IEF) <- gsub("SPY.","", colnames(SPY))
colnames(IEF) <- gsub("IEF.","", colnames(IEF))
head(IEF,2)
             Open   High    Low  Close Volume Adjusted
#2013-12-16 100.86 100.87 100.52 100.61 572400    98.36
#2013-12-17 100.60 100.93 100.60 100.93 694800    98.67

使用quantmod中的函数创建新列很简单,例如,

SPY$logRtn <- periodReturn(Ad(SPY),period='daily',subset=NULL,type='log')
IEF$logRtn <- periodReturn(Ad(IEF),period='daily',subset=NULL,type='log')
head(IEF,2)
#              Open   High    Low  Close Volume Adjusted    logRtn
#2013-12-16 100.86 100.87 100.52 100.61 572400    98.36 0.0000000
#2013-12-17 100.60 100.93 100.60 100.93 694800    98.67 0.0031467

而是创建一个新的语句来执行每个ETF的计算,我想改用一个列表。这是一般的想法:

etfList
#[1] "IEF" "SPY"
etfColName = "logRtn"

for (etfName in etfList) {
    newCol <- paste(etfName, etfColName, sep = "$"
    newcol <- periodReturn(Ad(etfName),period='daily',subset=NULL,type='log')
}

当然,使用字符串(显然)并不起作用,因为

typeof(newCol) # is [1] "character"
typeof(logRtn) # is [1] "double"

我已经尝试了所有我能想到的(至少两次)将字符串etfName $ etfColName强制转换为我可以分配计算的对象。

我已经查看了许多适用于data.frames的变体,例如来自dplyr的mutate(),但不能处理xts数据文件。我可以将数据集从xts反向转换为data.frames,但这非常糟糕(至少可以说)。

那么,任何人都可以建议一个优雅而直接的解决方案来解决这个问题(即,在不到25行的代码中)?

我将非常感激,当我足够购买我自己的NFL球队时,你将永远在主人的盒子里有一个荣誉的地方。

2 个答案:

答案 0 :(得分:1)

如果将数据存储在新环境中,则此类任务会更加轻松。然后,您可以使用eapply循环遍历环境中的所有对象并向其应用函数。

library(quantmod)
etfList <- c("IEF","SPY")

# new environment to store data
etfEnv <- new.env()
# use env arg to make getSymbols load the data to the new environment
getSymbols(etfList, from="2013-12-15", to="2013-12-31", env=etfEnv)

# function containing stuff you want to do to each instrument
etfTransform <- function(x, ...) {
  # remove instrument name prefix from colnames
  colnames(x) <- gsub(".*\\.", "", colnames(x))
  # add return column
  x$logRtn <- periodReturn(Ad(x), ...)
  x
}
# use eapply to apply your function to each instrument
etfData <- eapply(etfEnv, etfTransform, period='daily', type='log')

答案 1 :(得分:0)

(我没有意识到你发布了一个可重现的例子。)

看看这是否有用:

 etfColName = "logRtn"
 for ( etfName in etfList ) {
     newCol <- get(etfName)[ ,  etfColName]
     assign(etfName, cbind( get(etfName), 
                            periodReturn( Ad(get(etfName)), 
                                          period='daily', 
                                         subset=NULL,type='log')))
                        }

> names(SPY)
[1] "SPY.Open"      "SPY.High"      "SPY.Low"       "SPY.Close"    
[5] "SPY.Volume"    "SPY.Adjusted"  "logRtn"        "daily.returns"

我不是一个quantmod用户,只是从我看到的行为中我认为Ad函数返回一个命名向量。 (所以我不需要做任何命名。)

R不是一种宏语言,这意味着您不能将字符值串起来并期望它们像在命令行中键入它们一样执行。 getassign函数允许您根据字符值从数据对象环境中“拉”和“推”项,但不应使用$ - 函数与他们合作。

我仍然没有看到newCol的创建与您的代码尝试创建的实际新列之间存在关联。他们有不同的拼写,所以会有不同的栏目...如果我能弄清楚你在尝试什么。