Excelで簡単に実行できるRで簡単な操作を実行したいと思います。
Kという5045個のエントリで構成される列があります。最初の値がL1=100 + K [1]、2番目がL2 = L1 + K [2]、3番目がL3=である2番目の列Lを作成します。 L2 +K[3]など。
Rでこれを行う簡単な方法はありますか?Excelでは、列をプルダウンするだけです。
次のようなものを試してください
L <- 100 + cumsum(K)
1つのアプローチは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が回答で提案したものです)。
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
したがって、可能な限り組み込み関数を使用してください。また、組み込みがない場合は、コンパイラパッケージを試してください。多くの場合、より高速なコードを提供します。
以下に、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
ます。