为什么除以常量 R 中的 xts 对象会导致矩阵对象(丢失 Date 列)?

why dividing by a constant an xts object in R results in a matrix object (losing the Date column)?

感谢您在以下方面的帮助:

为什么 R 中的 xts 对象除以常量会得到矩阵对象(Date/index 列丢失)? 我希望生成的对象是一个 xts 对象,就像输入 xts 一样,只是列值除以常量。为什么会发生这种情况以及如何避免?

我观察到的问题示例。

代码摘录:

TradeProfit <- as.xts(ifelse(is.na(lag(GLD$Signal, 1)) == 0 & GLD$Signal != lag(GLD$Signal, 1), GLD$TotTradCapital, NA ))
TradeProfit <- na.omit(TradeProfit)

TradeProfitPerc <- ifelse(is.na(lag(TradeProfit,1)) == 0, TradeProfit / 100, NA)
TradeProfitPerc <- na.omit(TradeProfitPerc)

> class(TradeProfit)
[1] "xts" "zoo"

> head(TradeProfit)
              Signal
2012-08-15  0.000000
2012-11-02  6.970001
2012-11-06  6.970001
2013-08-09 46.410003
2013-08-14 46.410003
2013-09-27 46.380004

head(TradeProfitPerc)
        Signal
[1,] 0.06970001
[2,] 0.06970001
[3,] 0.46410003
[4,] 0.46410003
[5,] 0.46380004
[6,] 0.46380004

> class(TradeProfitPerc)
[1] "matrix"
> 

问题是 TradeProfitPerc 丢失了我想要保留的日期 column/index。另外,由于 TradeProfit 是一个 xts 对象,为什么除法会导致将 xts 转换为矩阵对象的奇怪行为?如何保留 xts 属性? 谢谢!

如果我是你,我会简单地向现有对象添加一列,这将保留 xts class.

GLD <- xts(matrix(1:10,ncol=2),Sys.Date()+0:4)
colnames(GLD) <- c("Signal","TotTradCapital")
TradeProfit <- as.xts(ifelse(is.na(lag(GLD$Signal, 1)) == 0 & GLD$Signal != lag(GLD$Signal, 1), GLD$TotTradCapital, NA ))
TradeProfit <- na.omit(TradeProfit)

TradeProfit$TradeProfitPerc <- ifelse(!is.na(lag(TradeProfit,1)), TradeProfit / 100, NA)

           Signal TradeProfitPerc
2017-06-06      7              NA
2017-06-07      8            0.08
2017-06-08      9            0.09
2017-06-09     10            0.10

这是一个可重现的最小示例:

library(quantmod)
getSymbols("GLD")
GLD$GLD.SMA <- SMA(Cl(GLD), 50)
GLD$Signal <- Cl(GLD) > GLD$GLD.SMA

TradeProfit <- as.xts(ifelse(!is.na(lag(GLD$Signal, 1)) &
                             GLD$Signal != lag(GLD$Signal, 1), 100, NA))
TradeProfit <- na.omit(TradeProfit)

TradeProfitPerc <- ifelse(!is.na(lag(TradeProfit,1)), TradeProfit / 100, NA)
TradeProfitPerc <- na.omit(TradeProfitPerc)

问题在于,在 xts 对象上调用 is.na 会产生一个没有行名称的逻辑矩阵,并且 ifelse returns 会产生一个具有与其相同形状和属性的对象第一个参数。所以 TradeProfitPerc 是一个没有行名的矩阵,因为这是传递给 ifelse.

的第一个参数的结构

计算 TradeProfit 时这不是问题,因为 & GLD$Signal != lag(GLD$Signal, 1)GLD$Signal != lag(GLD$Signal, 1) 比较 returns xts 对象,以及 xts 对象和非 xts 对象之间的逻辑比较产生 xts 对象。例如:

str(FALSE & xts(TRUE, Sys.Date()))
An 'xts' object on 2017-06-05/2017-06-05 containing:
  Data: logi [1, 1] FALSE
  Indexed by objects of class: [Date] TZ: UTC
  xts Attributes:  
 NULL

您可以通过避免 ifelse 并直接子集化来避免这种情况:

GLD$TotTradCapital <- 500
# rows where Signal is NA will be FALSE and therefore not included in TradeProfit
TradeProfit <- GLD[GLD$Signal != lag(GLD$Signal, 1), "TotTradCapital"]
TradeProfitPerc <- TradeProfit / 100