2012-10-24 101 views
5

我想R中,很容易在Excel中完成執行一個簡單的操作:連續添加值前一個R中

我有一個山坳由5045項叫K.我想創建第二個列L,其中第一個值是L1 = 100 + K [1],第二個是L2 = L1 + K [2],第三個是L3 = L2 + K [3]依此類推。

有沒有一種簡單的方法來做到這一點在R?在Excel中,只需拉下列。

回答

7

嘗試像

L <- 100 + cumsum(K) 
+0

+1整潔 - 當我開始寫答案的時候,我錯過了,只是因爲當我剛完成時纔開始寫作。 –

+0

+1我很難找到一個矢量化的解決方案,並回到使用'for'循環。我的答案中的時間表明,與使用'cumsum'相比,這非常緩慢。 –

4

一種方法是使用cumsum()和欺騙了一些。例如,給定K

K <- 1:10 

,並讓事情變得簡單,我加入1(不100)到K[1],我們要生產:

> 1 + K[1] 
[1] 2 
> (1 + K[1]) + K[2] 
[1] 4 
> ((1 + K[1]) + K[2]) + K[3] 
[1] 7 
.... 

這是一個累積總和。我們需要用你想添加到第一個元素的常量來作弊,因爲我們只想要影響第一個元素,而不是添加到每個元素。因此,這是錯誤

> L <- cumsum(1 + K) 
> L 
[1] 2 5 9 14 20 27 35 44 54 65 

我們真正想要的是:

> L <- cumsum(c(1, K))[-1] 
> L 
[1] 2 4 7 11 16 22 29 37 46 56 

其中我們串接不斷向矢量K作爲第一個元素,並應用cumsum()到這一點,但下降的第一要素的輸出從cumsum()

當然,這可以在一個稍微簡單的方式來完成:

> L <- 1 + cumsum(K) 
> L 
[1] 2 4 7 11 16 22 29 37 46 56 

即計算cumusum()然後添加的常數(我現在看到的是@ gd047在他們的回答已經暗示了什麼。 )

0

以下顯示for基於循環的解決方案。這可能不是你想要的速度,其中向量化函數如cumsum要快得多。

a = 1:10 
b = vector(mode = "numeric", length = length(a)) 
b[1] = 1 + a[1] 

for(idx in 2:length(a)) { 
    b[idx] = a[idx] + b[idx - 1] 
} 

一些計時:

require(rbenchmark) 

for_loop_solution = function(a) { 
    b = vector(mode = "numeric", length = length(a)) 
    b[1] = 1 + a[1] 

    for(idx in 2:length(a)) { 
     b[idx] = a[idx] + b[idx - 1] 
    } 
    return(invisible(b)) 
} 

cumsum_solution = function(a) { 
    return(1 + cumsum(a)) 
} 

sample_data = 1:10e3 
benchmark(for_loop_solution(sample_data), 
      cumsum_solution(sample_data), 
      replications = 100) 
          test replications elapsed relative user.self 
2 cumsum_solution(sample_data)   100 0.013 1.000  0.011 
1 for_loop_solution(sample_data)   100 3.647 280.538  3.415 
    sys.self user.child sys.child 
2 0.002   0   0 
1 0.006   0   0 

這表明使用cumsum比使用顯式的for循環快幾百倍。當sample_data的長度增加時,這種效果將更加明顯。

0

如Paul Hiemstra所示,內建函數cumsum()很快。 但是,for循環解決方案可以通過使用編譯器包加速。

library(compiler) 
fls_compiled <- cmpfun(for_loop_solution) 

然後使用相同的數據讓我們運行benchmark如下

benchmark(for_loop_solution(sample_data), 
      cumsum_solution(sample_data), 
      fls_compiled(sample_data), 
      replications = 100) 
          test replications elapsed relative user.self 
2 cumsum_solution(sample_data)   100 0.013 1.000  0.013 
3  fls_compiled(sample_data)   100 0.726 55.846  0.717 
1 for_loop_solution(sample_data)   100 4.417 339.769  3.723 
    sys.self user.child sys.child 
2 0.000   0   0 
3 0.006   0   0 
1 0.031   0   0 

所以儘可能使用內建函數。 如果沒有內建,請嘗試編譯程序包。它通常提供更快的代碼。