2011-05-01 68 views
2

我正在使用一些圖形數據,這些數據主要集中在向量或列表中。
大多數時候我需要通過給定索引檢查向量/列表,並執行一些邏輯來確定當前元素的結果值。避免循環但保留索引信息

爲了更精確一點,考慮的代碼,這樣的片段:

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函數基本上也具有輸入行中的索引。

對於您對這些方法的想法,我將非常感激。

+0

這是在你的計算瓶頸?我的經驗法則是 - 如果它適用於for/while循環(並且你沒有大數據),循環就會很好並且很花哨。完全有可能得到一個小的可重現的例子嗎? – 2011-05-01 15:50:39

+0

我還沒有進入測量性能階段。寧可設計R風格,而不是一直循環。一旦我符合正確的思維框架,我可能會提出矢量化解決方案,而不必首先考慮循環。這就是我問的原因。 不幸的是,我現在無法提供任何可重複的示例 - 我正在考慮一些一般提示,而不是解決一個給定的問題:)感謝您的答覆。 – chemical 2011-05-01 16:09:54

回答

1

那麼,你可以做矢量化的索引,這應該給你一個顯着的加速的機會。在一般情況下,而不是:

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

你可以這樣做:

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

*應用基本都是循環的外包裝,所以你會被轉換環路,他們獲得的最清晰的代碼。

編輯:小插圖,以補充註釋:

> 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 
+0

謝謝你的提示。我會嘗試使用這種方法。有一件事讓我想知道 - 你說*應用可能**最多**清除我的代碼 - 這是否意味着當我嘗試使用R的功能使用多個內核時,使用* apply將不會提供任何提升? – chemical 2011-05-01 19:08:39

+1

@chemical您必須考慮解釋R代碼的開銷,這可能很重要。 R做矢量運算,所以標量運算非常不理想;你可能會因此而獲得20-30倍的放緩,沒有並行性在這裏會有所幫助。 – mbq 2011-05-01 20:00:46

+1

使用apply可以幫助您在並行計算和單線程代碼之間切換。這並不意味着你的表現會得到提升(許多因素正在影響這一點,請參閱mbq的評論)。 – 2011-05-01 22:21:51