避免循环但保留索引信息

时间:2011-05-01 15:08:42

标签: r

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

为了更加精确,请考虑这样的代码片段:

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内部函数(带有索引的向量),它看到外部(在外部函数中声明)数据对象并使用提供的索引向量来执行逻辑
  3. 示例代码(更简单,与上面的代码无关):

    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函数基本上也会在输入行中包含索引。

    我会非常感谢你对这些方法的看法。

1 个答案:

答案 0 :(得分: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