【问题标题】:Subtract every column from each other in an xts object在 xts 对象中相互减去每一列
【发布时间】:2015-10-24 22:38:53
【问题描述】:

我是一个学习编码的新手,并且有一个 1000 行和 10 列的 xts 对象。我需要从彼此中减去每一列,创建一个新的 xts 对象来保留日期列。我尝试使用combn,但由于它做了A-B,所以无法让它创建B-A结果。我正在寻找的内容如下。

 DATA                                           RESULT
            A  B   C     --->               A-B   A-C  B-A  B-C  C-A  C-B
2010-01-01  1  3   5           2010-01-01   -2    -4    2    -2    4    2 
2010-01-02  2  4   6           2010-01-02   -2    -4    2    -2    4    2
2010-01-03  3  5   2           2010-01-03   -2     1    2     3   -1   -3 

【问题讨论】:

  • 您可以尝试使用outer 来获取列名的所有组合。
  • Akrun- 不熟悉外部。我尝试使用 test 作为 xts 对象: z
  • 在下面发布了一个解决方案。希望对你有帮助
  • 对于xts 对象,没有名为“日期”的列。应该是index

标签: r xts


【解决方案1】:

我们可以使用outer 获得列名的成对组合,subset 基于列名的数据集“xt1”,获得list 中的差异。

f1 <- Vectorize(function(x,y) list(setNames(xt1[,x]-xt1[,y],
                                         paste(x,y, sep='_'))))
lst <- outer(colnames(xt1), colnames(xt1), FUN = f1)

我们将Filter 排除具有sum=0list 元素,即A-AB-BC-Ccbind 列之间的差异,以获得预期的输出。

 res <- do.call(cbind,Filter(sum, lst))
 res[,order(colnames(res))]
 #            A_B A_C B_A B_C C_A C_B
 #2010-01-01  -2  -4   2  -2   4   2
 #2010-01-02  -2  -4   2  -2   4   2
 #2010-01-03  -2   1   2   3  -1  -3

数据

 d1 <- data.frame(A=1:3, B=3:5, C=c(5,6,2))
 library(xts)
  xt1 <- xts(d1, order.by=as.Date(c('2010-01-01', '2010-01-02', '2010-01-03')))

【讨论】:

  • akun- 我在 xts 之后使用 str(test) 时的 xts 对象测试 属性:它说 List of 2 $ src : chr "yahoo" $ updated: POSIXct[1:1], format: " 2015-08-10 14:00:08" 所以当我使用 test 尝试你的代码时,它给了我 NULL。这是原因吗?如果是这样,有关如何解决的任何建议?谢谢
  • @doug 无论如何,我根据您展示的内容创建了一个 xts 对象,并获得了您展示的确切输出。
  • @doug 你说的是dimnames 属性中的NULL 吗?就我而言,它是 NULL,因为我没有创建一个。
【解决方案2】:

我使用以下方法构建数据:

x <- zoo::zoo(
    data.frame(
        A = c(1, 2, 3), 
        B = c(3, 4, 5), 
        C = c(5, 6, 2)), 
    order.by = as.Date(c("2010-01-01", "2010-01-02", "2010-01-03")))

然后我定义了一个函数来创建所有可能的两组对:

cross <- function(x, y = x) {

    result <- list()

    for (a in unique(x)) {

        for (b in unique(y)) {

            result <- append(result, list(list(left = a, right = b)))
        }
    }

    result
}

回答你的问题:

# Build a list of column combinations
combinations <- cross(names(x), setdiff(names(x), names(x)[1]))

# Remove any entries where the left equals the right
combinations <- combinations[vapply(combinations, function(x) { x$left != x$right }, logical(1))]

# Build a user friendly list of names
names(combinations) <- vapply(combinations, function(x) { paste0(x$left, "-", x$right) }, character(1))

# Do the actual computation and combine the results into one object 
do.call(cbind, lapply(combinations, function(x, data) { data[, x$left, drop = T] - data[, x$right, drop = T] }, data = x))

【讨论】:

  • 这很好用。我现在正试图通过逻辑工作,以便我可以成为一个更好的程序员。感谢您和 akrun 的帮助和快速响应。道格
  • 在 RStudio 中,单击一个函数并按 F1 以阅读有关它的更多信息。祝你好运!
猜你喜欢
  • 2013-05-27
  • 2020-11-15
  • 1970-01-01
  • 2018-01-27
  • 2019-06-28
  • 1970-01-01
  • 2019-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多