【问题标题】:Avoiding loops but preserving index info避免循环但保留索引信息
【发布时间】:2011-08-16 11:48:12
【问题描述】:

我正在处理一些类似图表的数据,这些数据主要收集在向量或列表中。
大多数时候,我需要通过给定的索引检查向量/列表,并执行一些逻辑来确定当前元素的结果值。

更准确地说,考虑这样一段代码:

for (i in 1:(length1 - 1))
    for (j in (i + 1):length2)
        for (k in 1:length3) {
            d1 <- data[i, k]
            d2 <- data[j, k]
            if (d1 != d2)
                otherData[i, j, k] <- list(c(min(d1, d2), max(d1, d2)))
            else
                otherData[i, j, k] <- list(c(1, 1))
        }

我的问题是:
- 这是一个很好的解决方案:

  1. 创建索引向量,然后
  2. lapply 内部函数(采用索引向量)查看外部(在外部函数中声明)数据对象并使用提供的索引向量来执行逻辑

示例代码(更简单,与上面的代码无关):

someFunc <- function(data) {
    n <- length(data)
    f <- function(i) {
        return (doSthWith(data[i], i))
        # do some logic with both the data and the index
    }
    return (sapply(1:n, f))
}

我想出的另一个解决方案是创建一个 data.frame 并使索引成为数据的一部分,因此 lapply 函数基本上也会在输入行中具有索引。

非常感谢您对这些方法的看法。

【问题讨论】:

  • 这是您计算中的瓶颈吗?我的经验法则是 - 如果它适用于 for/while 循环(并且您没有大数据),那么循环就很好而且花花公子。是否有可能得到一个可重复的小例子?
  • 我还没有进入衡量性能的阶段。宁愿设计 R 风格而不是一直循环。一旦我适应了正确的思维框架,我可能会想出矢量化解决方案,而无需首先进行循环思考。这就是我问的原因。不幸的是,我现在无法提供任何可重现的示例 - 我正在考虑一些一般性提示,而不是解决一个给定的问题 :) 感谢您的回复。

标签: r


【解决方案1】:

好吧,您可以进行矢量化索引,这应该会给您一个显着加速的机会。一般来说,而不是:

for(a in A) for(b in B) something(x[a,b])

你可以这样做:

something_vectorized(x[as.matrix(expand.grid(A,B))])

*apply 基本上是循环包装器,因此您最多可以通过将循环转换为它们来获得清晰的代码。

编辑:补充评论的小插图:

> system.time(replicate(100,sum(sapply(1:1000,function(x) x^2))))
   user  system elapsed 
  0.385   0.001   0.388 
> system.time(replicate(100,sum((1:1000)^2)))
   user  system elapsed 
  0.002   0.001   0.003

【讨论】:

  • 感谢您的提示。我将尝试尝试这种方法。有一件事让我想知道 - 你说 *apply 可能最多清除我的代码 - 这是否意味着当我尝试使用 R 的功能来使用多个内核时使用 *apply 不会带来任何提升?
  • @chemical 您必须考虑解释 R 代码的开销,这可能很重要。 R 是用来做向量运算的,所以做标量运算是非常不理想的;因此,您可能会减速 20-30 倍,这里没有并行性有帮助。
  • 使用 apply 将帮助您在执行并行计算和单线程的代码之间切换。这并不意味着您会获得性能提升(许多因素会影响这一点,请参阅 mbq 的 cmets)。
  • 感谢您对矢量化的精彩解释,它提高了我对 R 的理解 :) 但是,我仍然想不出一种矢量化的方式来加速我在我的问题中发布的一堆代码.它对列表列表进行操作。我应该提供更多代码吗?也许通过解决这个单一问题,您可以向我展示比循环更好的一般方法。
猜你喜欢
  • 1970-01-01
  • 2015-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多