【问题标题】:Passing multiple arguments to Reduce将多个参数传递给 Reduce
【发布时间】:2012-09-05 01:22:30
【问题描述】:

我有一个 data.frames 列表,并希望使用各种权重对其列进行操作。

例如,从第二列中减去第一列(已解决,见下文);或从第二个的两倍(未解决)中减去第一个和第三个。

感谢在回复this 问题时获得的慷慨帮助,我使用Reduce 解决了没有权重的二维问题。

我希望能够灵活地使用权重 - 以及更高的尺寸。

到目前为止我所拥有的是:

priceList <- data.frame(aaa = rnorm(100, 100, 10), bbb = rnorm(100, 100, 10), 
                        ccc = rnorm(100, 100, 10), ddd = rnorm(100, 100, 10), 
                        eee = rnorm(100, 100, 10), fff = rnorm(100, 100, 10), 
                        ggg = rnorm(100, 100, 10)
                        )

colDiff <- function(x) 
    {
        Reduce('-', rev(x))
    }

tradeLegsList <- combn(names(priceList), 3, function(x) priceList[x], simplify = FALSE)

tradeList <- lapply(tradeLegsList, colDiff)

据我所知,Reduce 并非旨在接受多个参数。

我可以用2* tradeLegsList[[1]]$bbb - tradeLegsList[[1]]$aaa - tradeLegsList[[1]]$ccc 和一些循环来做这个很长的路要走,但它看起来不像R 方式

有没有办法传入权重向量?

理想情况下,我会将w = c(-1, 2, -1) 之类的参数传递给colDiff(或Reduce)函数......或类似的东西。

【问题讨论】:

  • 如果您的数据与您的示例中的一样,即所有 numeric 并且每个列表元素具有相同的尺寸,那么我强烈建议您将数据存储在 3d 数组中。然后你想要做的事情可以用%*%(矩阵乘法)和可能的aperm单行来完成。
  • 是的,这就是数据准备好后的样子。谢谢,我会调查的。

标签: r reduce


【解决方案1】:

没错,Reduce 不适合允许多个参数,每个归约只允许两个参数。因此,最简单的方法是对列表中的元素进行预乘 Reduce-ing。

以下是在您的 colDiff 函数定义中使用 mapply 执行此操作的解决方案。

更改 colDiff 的定义以允许权重向量,并使用 mapply 应用它 与SIMPLIFY = F

编辑

根据 cmets,权重取决于列数,不需要rev

长度权重

长度(x) == 1 -> w = 1
长度(x) == 2 -> w = c(-1, 1),
长度(x) == 3 -> w = c(-1, 2, -1),
长度(x) == 4 -> w = c(-1, 1, -1, +1)

weighting <- function(i){
  switch(i, 1, c(-1,1), c(-1,2,-1), c(-1,1,-1, 1))
}
colDiff <- function(x) 
    {
        w = weighting(length(x))
        Reduce('+', mapply('*', x, e2 = w, SIMPLIFY = F))
    }

那么这样的事情就可以了

tradeList <- lapply(tradeLegsList, colDiff)

您也可以保留函数式编程主题并使用Map,它是mapplySIMPLIFY = F 的简单包装器

colDiff <- function(x) 
        {
            w = weighting(length(x))
            Reduce('+', Map('*', x , e2 = w))
        }

您还可以在函数 colDiff 中预先定义权重(这可能更容易)。 weighting[[2]] 是 2 列时的权重,weighting[[3]] 是 3 列时的权重。

colDiff <- function(x) 
        {
         weighting <- list(1, c(-1,1), c(-1,2,-1), c(-1,1,-1, 1))             
            w = weighting[[length(x)]]
            Reduce('+', Map('*', x , e2 = w))
        }

【讨论】:

  • +1,谢谢。我认为您需要更改 Reduce 语句中的操作符号。即,使Reduce('-', ...Reduce('+', ... ...但这打破了w = NULL的情况...也许e2 = -w
  • 不清楚你的意思。如果您的 tradeLegList 元素之一是包含 aaabbbccc 列的 data.frame。如果w = c(-1,2,1),该函数应该给出-ccc - 2bbb - aaa。 (假设您在 Reduce 调用中颠倒了 x 的顺序
  • 道歉。 w = c(-1, 2, -1) 的期望结果是 -aaa +2bbb -ccc。您是否认为完整的解决方案是编写一个函数来将权重转换为适当的顺序,以便我们可以在Replace 中使用+
  • 那么是的,+ 是要走的路。为什么你原来有rev(x)
  • 权重是否取决于列名?如果是这样,可以更改解决方案以适应这种情况。
猜你喜欢
  • 2016-07-18
  • 2013-01-07
  • 2011-10-10
  • 2013-09-15
  • 2010-10-09
  • 2017-06-14
  • 2018-08-12
  • 2015-11-14
  • 1970-01-01
相关资源
最近更新 更多