Rコード最適化のコツと実例集
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
COLOR(magenta){SIZE(20){Rコード最適化のコツと実例集 (RjpW...
// 間瀬:2004.06.05 開始
#contents
~
この tips (集)では R コードの最適化のコツと、実際例を紹介...
私見によれば、個別の問題に特有な工夫を別にしても、R で高...
R はインタプリタ言語ですから、C 等に比べれば実行速度は原...
(1) 時間のかかる計算を内部的に C や FORTRAN サブルーチン...
(2) 関数のベクトル化。R の関数のほとんどは引数としてベク...
特に高速ベクトル化関数を意識した R コードを書くコツを身に...
なぜ高速化を意識したコードを書くことを心がける必要がある...
- R の主要な利用目的にランダムシミュレーションがあります...
- 統計計算では解を optim() 等の最適化関数を用いて数値的に...
- 必要になった時だけ最適化したコードを書くことはできませ...
- R で素朴なプログラムを実行しても、多くの場合何とかなる...
- これはまた R というプログラム言語の特性を理解することに...
もちろん、問題に素直なコードを書くことが基本であることは...
以下は私の個人的経験による R コードの高速化のコツをまとめ...
~
~
COLOR(red){注意}:system.time() 関数の返す5種類の時間のう...
タイム)、三番目がインタフェイス・表示等の時間を含んだ経過...
~
* 意味のあるときは常に、意味の無いときも常にベクトル化を...
ベクトル化されたシステム関数を極力使うベクトル化演算に徹...
## exp() 関数はベクトル化されている
> x <- runif(1000000)
> test1 <- function () { # 百万個の数の指数を個別に計算
res <- numeric(1000000)
for (i in 1:1000000) res[i] <- exp(x[i])
res}
> system.time(test1())
[1] 9.27 0.04 18.51 0.00 0.00
> system.time(res <- exp(x)) # ベクトル化演算で一気に計算
[1] 0.15 0.03 0.27 0.00 0.00
* むき出しの繰り返しは避ける [#pb51b837]
(ほとんど)同じことを2回以上していれば改良の余地があります...
## 2 で割る操作を毎回している問題コード
> x <- runif(1000000)
> system.time({c <- 0; for (i in 1:100000) c <- c + x[i]...
[1] 0.55 0.00 1.04 0.00 0.00
## 最後に割るだけで良い(し早い)
> system.time({c <- 0; for (i in 1:100000) c <- c + x[i]...
[1] 0.46 0.00 0.88 0.00 0.00
## for loop 無しの例
> system.time(print(sum(x/2)))
[1] 0.07 0.02 0.16 0.00 0.00
## これでも最後に一回割る方が数倍早い
> system.time(print(sum(x)/2))
[1] 0.02 0.00 0.05 0.00 0.00
注意:同じ操作を副関数化することはコードの簡潔化に有効で...
> test1 <- function () {
for (i in 1:1000) sum(runif(i))
}
> aux <- function (i) sum(runif(i)) # 副関数化
> test2 <- function () {
for (i in 1:1000) aux(i)
}
> c <- 0; for (i in 1:100) c <- c + system.time(test1())...
[1] 0.1299 0.0000 0.1303 0.0000 0.0000
> c <- 0; for (i in 1:100) c <- c + system.time(test2())...
[1] 0.1319 0.0000 0.1323 0.0000 0.0000 # 少し遅い
* 全体を操作せよ [#if173a98]
狭い部屋で作業するよりも、広い場所で仕事をするほうが当然...
## 1:100 一様乱数10個の平均値を1万個求める
> test1 <- function() {
res <- numeric(10000)
for (i in 1:10000) res[i] <- mean(sample(1...
res
}
> system.time(test1())
[1] 1.87 0.03 3.94 0.00 0.00
> test2 <- function() {
y <- matrix(0, nr=10000, nc=10) # 乱数全体...
for(i in 1:10000) y[i,] <- sample(1:100, 10)
res <- rowSums(y)/10 # 高速な行和...
}
> system.time(test2())
[1] 0.46 0.00 0.91 0.00 0.00
test1 も test2 も,1〜100までの非復元抽出による乱数ですね...
test3 <- function()
{
y <- matrix(sample(1:100, 10000*10, replace=TRUE), 1000...
rowMeans(y) ...
}
system.time(test3())
test3 は,test2 の 40 倍ほどの速度になります。
* リスト変数は高価と心得る [#n169a2ea]
例外として、リスト処理があります。(私の理解不足かもしれま...
> x <- list(rep(0,1000000)) # リストとして処理
> system.time(for (i in 1000000) x[[i]] <- 0)
[1] 0.22 0.02 0.24 0.00 0.00 # それなりに時間がかかる
> x <- numeric(1000000) # ベクトルとして処理
> system.time(for (i in 1000000) x[i] <- 0)
[1] 0 0 0 0 0 # 一瞬
list(rep(0,1000000)) により作られるリストに,x[[1]] ...
for (i in 1000000) x[[i]] <- 0 が遅いのは,i >= 2 の...
> n <- 1000000
> x <- list(rep(0,n)) # リストとして処理
> length(x)
[1] 1 # この時点では...
> system.time(for (i in n) x[[i]] <- 0)
ユーザ システム 経過
0.01 0.00 0.01
> length(x)
[1] 1000000 # この時点では...
# x[[1]][1]〜x[...
# x[[2]]〜x[[10...
やっている内容が違う(しかも,非効率的)ので,時間がかか...
1000000 個の要素を持つリストを作るのは vector("list", 100...
以下の正しいプログラムでは,実行時間はベクトルを使う場合...
x <- vector("list", n)
system.time(for (i in n) x[[i]] <- 0)
* 一つずつ沢山よりも、沢山を一度に [#f20ba136]
R は相当サイズの大きな変数を使ってもめげたりしません。必...
> x <- numeric(10000)
## 標準正規乱数, 1万個を一つずつ
> system.time(for (i in 1:10000) x[i] <- rnorm(1))
[1] 0.44 0.00 0.51 0.00 0.00
## 標準正規乱数, 1万個をいっぺんに
> system.time(x <- rnorm(10000))
[1] 0.01 0.00 0.01 0.00 0.00
> x <- numeric(100000)
## ベルヌイ試行, 10万個を一つずつ
> system.time(for (i in 1:100000) x[i] <- sample(c(0,1),...
[1] 3.87 0.00 3.89 0.00 0.0
## ベルヌイ試行, 10万個を一回に
> system.time(x <- sample(c(0,1), 100000, replace=TRUE))
[1] 0.01 0.01 0.03 0.00 0.00
## 関数呼出しはタダでないことを示す例
> test <- function() {} # 何もしない関数
> system.time(for(i in 1:100000) test()) # それでも呼出...
[1] 0.16 0.00 0.27 0.00 0.00
* 贅沢は素敵だ(花森安治、若い世代には意味不明?) [#ha026d...
上の系になりますが、予めサイズが分かっている変数(ベクトル...
## ベクトルを段々伸ばす
> x <- numeric(0)
> system.time(for (i in 1:10000) x[i] <- 0)
[1] 1.68 0.01 1.69 0.00 0.00
## 最初から必要なだけ入れ物を確保
> x <- numeric(10000)
> system.time(for (i in 1:10000) x[i] <- 0)
[1] 0.09 0.00 0.10 0.00 0.00
# 一様乱数の和が一万を越えるまでの必要個数
> test1 <- function() {
s <- c <- 1
while(s <= 10000) {s <- s + runif(1); c <- ...
print(c(s,c))
}
> system.time(test1())
[1] 10000.14 20093.00
[1] 0.51 0.00 0.67 0.00 0.00
> test2 <- function() {
x <- cumsum(runif(40000)) # 気前良く4万個...
print(sum(x <= 10000) + 1) # x <- 10000 で...
}
> system.time(test2())
[1] 20048
[1] 0.02 0.00 0.01 0.00 0.00
## ベクトルを段々伸ばす例(空いているメモリを必死に探し回...
> system.time({x <- NULL; for (i in 1:10000) x <- c(x,ru...
[1] 1.74 0.00 3.42 0.00 0.00
## 最初に場所を確保
> system.time({x <- numeric(10000); for (i in 1:10000) x...
[1] 0.28 0.00 0.50 0.00 0.00
# 最初に十分大きなベクトル用意し、最後に余分な部分を捨て...
test1 <- function() {
x <- numeric(0) # 空のベクトルから出発
for (i in 1:rnorm(1, m=3000, sd=200)) x[i] <- i
x
}
test2 <- function() {
x <- rep(NA,10000) # NA 値だけの十分大きなベ...
for (i in 1:rnorm(1, m=3000, sd=200)) x[i] <- i
na.omit(x) # NA 値部分を捨てる
}
system.time(x <- test1())
[1] 0.16 0.01 0.17 0.00 0.00
system.time(x <- test2())
[1] 0.03 0.00 0.03 0.00 0.00
length(x) # 実際必要だったベクトル長
[1] 3152
* 論理判断は守銭奴のごとくけちる [#t4f9ae2f]
ループと並ぶ高速化の敵は論理判断です。どんな言語でもこれ...
## 百万個の数のランダムな加減算(工夫で論理判断を掛け算で...
> x <- 1:1000000
> y <- sample(c(TRUE, FALSE), 1000000, replace = TRUE) #...
> s <- 0; system.time(for (i in 1:1000000) if (y[i]) s <...
[1] 5.99 0.01 6.01 0.00 0.00
> system.time(s <- sum((2*y-1)*x)) # 工夫で論値判断を無...
[1] 0.21 0.05 0.28 0.00 0.00
また abs() 関数等はいわば関数自身が論理判断を内蔵していま...
裸々な論理判断を無くすことができます。
また if, while 文はベクトル化されていない稀な構文の例です...
## 混合正規分布乱数一万個を生成
> x <- rnorm(10000) # N(0,1) 乱数一万個
> y <- rnorm(10000, sd = 2, mean= 1) # N(1,2^2) 乱数一万個
> w <- numeric(10000) # 結果をいれるベク...
> test1 <- function(){ # if 文を使う素朴な...
for (i in 1:10000)
if (runif(1)< 0.35) w[i] <- x[i] else w[i...
w
}
> system.time(test1())
[1] 0.51 0.00 0.52 0.00 0.00
> system.time(w <- ifelse(runif(10000)<0.35, x,y)) # ife...
[1] 0.02 0.00 0.01 0.00 0.00
> system.time({p <- (runif(10000)<0.35); w <- p*x+(1-p)*...
[1] 0.01 0.00 0.01 0.00 0.00
データの順序を問題にしないのなら,パラメータの異なる複数...
以下の方法は,上の例の掛け算を利用する方法(三番目)より...
system.time({r <- rbinom(1, n, 0.35); w3 <- c(rnorm(r), ...
* ベクトルは添字で操作せず、(論理)添字集合で操作する [#kb...
ベクトルの部分ベクトルを x[3] の如く、個々の成分で操作す...
x[x < 0] # x の負の要素だけからなるベクトル
x[0 < x & x < 1] # 区間 (0,1) に入る要素からなるベクトル
x[x == 0] # 値が 0 に等しい要素からなるベクトル
x[x != NA] # 欠損値を取り除いたベクトル
x[x %% 3 == 0] # 3 の倍数からなる要素のベクトル
x[y == 0] # y の 0 の要素に対応する x の要素からなるベク...
残念なことに,欠損値が絡むと,上の例のはすべて(!)うま...
四番目以外は,要素に NA がなければちゃんと動く。しかし,N...
> (x <- c(-2, 0, 3, NA, 9, 0.4, 5, 0))
[1] -2.0 0.0 3.0 NA 9.0 0.4 5.0 0.0
# 一番目
> x[x < 0]
[1] -2 NA
# 二番目
> x[0 < x & x < 1]
[1] NA 0.4
# 三番目
> x[x == 0]
[1] 0 NA 0
# 四番目
> x[x != NA]
[1] NA NA NA NA NA NA NA NA # さすがに予想外の結果だ...
# 五番目
> x[x %% 3 == 0]
[1] 0 3 NA 9 0
# 六番目
> (y <- c(NA, 1, 0, 1, 0, 1, 0, 1))
[1] NA 1 0 1 0 1 0 1
> x[y == 0]
[1] NA 3 9 5
欠損値があっても正しく機能するようにするには,subset 関数...
> (x <- c(-2, 0, 3, NA, 9, 0.4, 5, 0))
[1] -2.0 0.0 3.0 NA 9.0 0.4 5.0 0.0
> # 一番目
> subset(x, x < 0)
[1] -2
> # 二番目
> subset(x, 0 < x & x < 1)
[1] 0.4
> # 三番目
> subset(x, x == 0)
[1] 0 0
> # 四番目
> subset(x, !is.na(x))
[1] -2.0 0.0 3.0 9.0 0.4 5.0 0.0
> # または
> x[!is.na(x)]
[1] -2.0 0.0 3.0 9.0 0.4 5.0 0.0
> # 五番目
> subset(x, x %% 3 == 0)
[1] 0 3 9 0
> # 六番目
> (y <- c(NA, 1, 0, 1, 0, 1, 0, 1))
[1] NA 1 0 1 0 1 0 1
> subset(x, y == 0)
[1] 3 9 5
教訓:欠損値があるときの挙動もちゃんと確認しておこう(実...
次の性質も覚えておくと役にたつことがあります(参考例クイッ...
x <- runif(10)
y <- x[x < 0] # 長さ0のベクトル(空集合)になる
all.equal(x, c(x,y)) # 長さ0のベクトルを付け加えても変化...
TRUE
# 論理値 TRUE, FALSE は数が要求される局面では整数 1,0 に...
> TRUE + TRUE +FALSE # 1 + 1 + 0 と解釈される
[1] 2
> sum(c(TRUE, TRUE, FALSE, TRUE))
[1] 3
> FALSE * 0.5 # 0 * 0.5 と解釈される
[1] 0
> x <- 0:5
> x < 3 # 論理値ベクトルになる
[1] TRUE TRUE TRUE FALSE FALSE FALSE
> sum(x < 3) # 3 未満の x の要素の数
[1] 3
* 返り値 [#g2273a6d]
これは高速化という意味ではなく、コードの簡潔化という意味...
# 代入し、そして和を求める
x <- y
z <- sum(x)
# 一行で書けば(x に y を代入し、その暗黙の返り値、つまり...
z <- sum(x <- y)
y <- z
x <- exp(y)
# 一行で書けば
x <- exp(y <- z)
# 実行時間は少し遅くなるらしい
> system.time(for(i in 1:10000) {z <- runif(1000); y <- ...
[1] 6.27 0.00 6.28 0.00 0.00
> system.time(for(i in 1:10000) {x <- exp(y <- (z <- run...
[1] 6.46 0.00 6.47 0.00 0.00
ほとんど誤差範囲で,むしろ後者の方が速いのでは?@rem:2010...
> n <- 100000
> system.time(for(i in 1:n) {z <- runif(1000); y <- z^2;...
ユーザ システム 経過
9.788 0.815 10.558
> system.time(for(i in 1:n) {x <- exp(y <- (z <- runif(1...
ユーザ システム 経過
9.715 0.827 10.472
* 問題を変形する [#c091531e]
R に助けてもらうことばかり考えず、R を助けてあげることも...
* デバッグしやすさを最初から考慮する [#t18a8ffe]
経験によれば次の近似的不等式が成り立ちます:
デバッグに必要な時間 >= (プログラミングに要するトータル...
ですから最初からデバッグしやすいようにコーディングすべき...
これには決め手はありませんが、いくつかのコツはあります。
-多重ループは混乱しやすい。ループが閉じるところにコメント...
-(日本語の)コメントを随所に置く
-分かりやすい、そして他と紛らわしくない変数名を使う。特に...
-永続付値演算子 <<- はしばしば便利ですが、何をしているの...
-プログラムを一連の関数に分割する。特に補助的な(しかし本...
-プログラムが求める結果を確かに計算していることを確認でき...
COLOR(red){誤つは人の常、デバッグは世の常、そして結果の正...
* 人生という長期的スパンで最適化を考える [#f78fa9ae]
高速化はあくまで手段であって、最終目的ではありません。高...
* 違いのわかる(気になる)人向け [#p210557e]
- 頻繁に使う定数は変数に代入し、変数として引用する。COLOR...
> system.time(for (i in 1:1000000) sample(1:52))
[1] 41.95 0.31 84.71 0.00 0.00
> a <- 1:52
> system.time(for (i in 1:1000000) sample(a)) # 少しは早い
[1] 37.29 0.00 74.63 0.00 0.00
- 既存変数を再利用(変数の構造・サイズが変わる場合はどうか...
> test1 <- function() {x <- runif(1000000); y <- x^2} # ...
> system.time(test1())
[1] 0.62 0.04 0.67 0.00 0.00
> test2 <- function() {x <- runif(1000000); x <- x^2} # ...
> system.time(test2())
[1] 0.48 0.03 0.50 0.00 0.00
- 永続付値(他の環境中の変数への付値)は手間がかかる。COL...
> test1 <- function(){x <- runif(10000)} # 自前の環境中...
> test2 <- function(){x <<- runif(10000)} # 親環境中の x...
> rm(x); c = 0; for(i in 1:100) c <- c + system.time(tes...
[1] 0.0015 0.0000 0.0020 0.0000 0.0000
> x
Error: Object "x" not found # 変数 x は関...
> x <- numeric(10000); c = 0; for(i in 1:100) c <- c + s...
[1] 0.0018 0.0000 0.0021 0.0000 0.0000
> x[1:5] # 当然 x は存在
[1] 0.02132324 0.36266310 0.50504673 0.89662908 0.67079898
- 変数初期化のコツ。同一のベクトル、配列変数を全要素 0 で...
> x=1:5
> system.time(for(i in 1:10^6) y <- numeric(5))
[1] 6.22 0.03 6.34 0.00 0.00
> system.time(for(i in 1:10^6) y <- 0*x)
[1] 2.94 0.01 3.00 0.00 0.00
> system.time(for(i in 1:10^6) y <- x-x)
[1] 2.58 0.01 2.75 0.00 0.00
> x=matrix(1:16, nc=4, nr=4)
> system.time(for(i in 1:10^4) y <- matrix(0, nc=4, nr=...
[1] 0.35 0.00 0.38 0.00 0.00
> system.time(for(i in 1:10^4) y <- 0*x)
[1] 0.04 0.01 0.05 0.00 0.00
> system.time(for(i in 1:10^4) y <- x-x)
[1] 0.04 0.00 0.04 0.00 0.00
-行列・配列の添字に関するCOLOR(red){ループは順序が大事}、...
x <- array(1:10^6, c(100, 100, 100))
ijk <- function() { # 添字の順にアクセス
for (i in 1:100) for (j in 1:100) for (k in 1:1...
}
ikj <- function() { # こんなことをする人はいないだろうが
for (i in 1:100) for (j in 1:100) for (k in 1:1...
}
kji <- function() { # 添字の逆順にアクセス
for (i in 1:100) for (j in 1:100) for (k in 1:1...
}
e <- function() { # 添字を全く使わない例
for (e in x) e
}
> system.time(ijk())
[1] 3.71 0.00 3.72 0.00 0.00
> system.time(ikj())
[1] 3.56 0.00 3.58 0.00 0.00
> system.time(kji())
[1] 3.26 0.00 3.27 0.00 0.00
> system.time(e())
[1] 0.26 0.00 0.28 0.00 0.00
* 補遺、それでもまだ遅いと文句の多い人は [#z79a5f55]
- COLOR(blue){金持なら:} CPU 速度の早い機械を買う、メモ...
- COLOR(blue){金がなければ:} 線形関数数値ライブラリ BLAS...
- COLOR(blue){環境に恵まれれていれば:} 周りの R wizard ...
- COLOR(blue){Tierney 氏のバイトコンパイル関数}を使ってみ...
- COLOR(blue){プログラミングに堪能なら:} C, FORTRAN サブ...
- COLOR(blue){頭に自信があれば:} 計算機を使わず、頭を使...
- COLOR(blue){上のいずれにも該当しなければ:} さっさとあ...
~
以上を参考に R プログラミングに精進して下さい。いつの日か...
* コード最適化の具体例 [#x2ef9ff6]
以下コード最適化の具体例を初心者への参考にいくつか挙げた...
** (1) r-help 記事より [[Rコードの最適化(初心者用メモ)]...
** (2) Q&A 記事より [[Rコード最適化例:空間点パターンのメ...
** (3) 「The R Book」 中の例を元にして [[Rコードの最適化...
** (4) 「工学のためのデータサイエンス入門」中の例を元にし...
** (5) [[Rコードの最適化例:ベクトルはベクトルとして操作...
** (6) [[Rコードの最適化例:配列はベクトルとして操作する]...
** (7) [[Rコードの最適化例:レスリー行列による個体群成長]...
** (8) [[Rコードの最適化例:混合正規乱数の発生コード]] 舟...
** (9) [[Rコードの最適化例:行が同じ数かどうかの判定]] r-...
** (10) [[Rコードの最適化例:行列のクロス積]] r-help 記事...
** (11) 行列の成分毎の積 r-help 記事より(2005.04.17) [#...
行列と1列行列の成分毎の積(行列としての積でなく)は、行列...
> mm <- matrix(1, 1000, 1000)
> ee <- matrix(1:100,nc=1)
> system.time(mm*ee[,], TRUE) # 行列 ee を掛ける
[1] 0.26 0.02 0.28 NA NA
> system.time(mm*c(ee), TRUE) # ee をベクトルとした上...
[1] 0.07 0.00 0.07 NA NA
おもしろい現象がある。R を起動した後最初に実行するときと...
なお,ee のサイズが 100 なのは間違いかな?@rem:2010/05/20
# 一回目
> mm <- matrix(1, 1000, 1000)
> ee <- matrix(1:100,nc=1)
> system.time(mm*ee[,], TRUE) # 行列 ee を掛ける
ユーザ システム 経過
0.033 0.006 0.039
> system.time(mm*c(ee), TRUE) # ee をベクトルとした上...
ユーザ システム 経過
0.006 0.006 0.013
# 二回目
> mm <- matrix(1, 1000, 1000)
> ee <- matrix(1:100,nc=1)
> system.time(mm*ee[,], TRUE) # 行列 ee を掛ける
ユーザ システム 経過
0.007 0.006 0.012
> system.time(mm*c(ee), TRUE) # ee をベクトルとした上...
ユーザ システム 経過
0.006 0.007 0.013
なお,このときの R のバージョンがいくつかによりますが(R-...
> class(ee[,]) # ee[,] は,ベクトル!!
[1] "integer"
> class(c(ee))
[1] "integer"
> class(ee) # ee は行列なので,
[1] "matrix"
> system.time(mm*ee, TRUE) # これは,エラーになる
以下にエラー mm * ee : 適切な配列ではありません
Timing stopped at: 0 0 0
* コメント、「俺ならこうする」等ありましたら以下にどうぞ ...
-RjpWiki 一周年記念コンテンツにふさわしい内容ではないでし...
-因みに論理判断が遅いのは、判断の結果次第で次に行う処理が...
-Rの持つ組み込みベクトル化機能を使うと速いのは、「メモリ...
-計算機の記憶領域は階層化されている。メモリは小さいがデー...
-R のライブラリは FORTRAN で書かれているのだろうか。~
配列の格納法(メモリ上の配置)から考えると,C とは異なり...
a <- function()
{
x <- matrix(1:100000, nr=20000, nc=5)
for (loop in 1:50) {
for (i in 1:20000) {
for (j in 1:5) {
x[i,j]
}
}
}
}
b <- function()
{
x <- matrix(1:100000, nr=20000, nc=5)
for (loop in 1:50) {
for (j in 1:5) {
for (i in 1:20000) {
x[i,j]
}
}
}
}
system.time(a())
system.time(b())
> system.time(a())
[1] 31.49 3.27 46.92 0.00 0.00
> system.time(b())
[1] 26.09 2.85 38.93 0.00 0.00
追試希望。 -- &new{2004-06-22 (火) 19:27:10};
-確かに,y <- 0*x は速いですね。y <- x-x の方がもう少しだ...
- 1で初期化する場合は0*x+1よりx^0が高速。さらに論理値で良...
- 行列の行や列に対する演算には、rowMeansなどを使う方法とa...
- そういうことは,オンラインヘルプにちゃんと書いてありま...
- sample(1:n,m) やa<-1:n; sample(a,m)より sample.int(n,m)...
- その差は,ノミの金玉くらいだ -- &new{2013-09-20 (金) 1...
> library(rbenchmark)
> benchmark(sample(1000, 1e6, replace=TRUE), sample.int(...
test replications e...
2 sample.int(1000, 1e+06, replace = TRUE) 100 ...
1 sample(1000, 1e+06, replace = TRUE) 100 ...
なぜそうなるかは,sample 関数を表示してみると分かる。つま...
> sample
function (x, size, replace = FALSE, prob = NULL)
{
if (length(x) == 1L && is.numeric(x) && x >= 1) {
if (missing(size))
size <- x
sample.int(x, size, replace, prob)
}
else {
if (missing(size))
size <- length(x)
x[sample.int(length(x), size, replace, prob)]
}
}
else 節はどういうことかというと,第1引数にベクトルを指定...
> library(rbenchmark)
> benchmark(sample(1:1000, 1e6, replace=TRUE), sample(10...
test replications e...
3 sample.int(1000, 1e+06, replace = TRUE) 100 ...
1 sample(1:1000, 1e+06, replace = TRUE) 100 ...
2 sample(1000, 1e+06, replace = TRUE) 100 ...
#comment
終了行:
COLOR(magenta){SIZE(20){Rコード最適化のコツと実例集 (RjpW...
// 間瀬:2004.06.05 開始
#contents
~
この tips (集)では R コードの最適化のコツと、実際例を紹介...
私見によれば、個別の問題に特有な工夫を別にしても、R で高...
R はインタプリタ言語ですから、C 等に比べれば実行速度は原...
(1) 時間のかかる計算を内部的に C や FORTRAN サブルーチン...
(2) 関数のベクトル化。R の関数のほとんどは引数としてベク...
特に高速ベクトル化関数を意識した R コードを書くコツを身に...
なぜ高速化を意識したコードを書くことを心がける必要がある...
- R の主要な利用目的にランダムシミュレーションがあります...
- 統計計算では解を optim() 等の最適化関数を用いて数値的に...
- 必要になった時だけ最適化したコードを書くことはできませ...
- R で素朴なプログラムを実行しても、多くの場合何とかなる...
- これはまた R というプログラム言語の特性を理解することに...
もちろん、問題に素直なコードを書くことが基本であることは...
以下は私の個人的経験による R コードの高速化のコツをまとめ...
~
~
COLOR(red){注意}:system.time() 関数の返す5種類の時間のう...
タイム)、三番目がインタフェイス・表示等の時間を含んだ経過...
~
* 意味のあるときは常に、意味の無いときも常にベクトル化を...
ベクトル化されたシステム関数を極力使うベクトル化演算に徹...
## exp() 関数はベクトル化されている
> x <- runif(1000000)
> test1 <- function () { # 百万個の数の指数を個別に計算
res <- numeric(1000000)
for (i in 1:1000000) res[i] <- exp(x[i])
res}
> system.time(test1())
[1] 9.27 0.04 18.51 0.00 0.00
> system.time(res <- exp(x)) # ベクトル化演算で一気に計算
[1] 0.15 0.03 0.27 0.00 0.00
* むき出しの繰り返しは避ける [#pb51b837]
(ほとんど)同じことを2回以上していれば改良の余地があります...
## 2 で割る操作を毎回している問題コード
> x <- runif(1000000)
> system.time({c <- 0; for (i in 1:100000) c <- c + x[i]...
[1] 0.55 0.00 1.04 0.00 0.00
## 最後に割るだけで良い(し早い)
> system.time({c <- 0; for (i in 1:100000) c <- c + x[i]...
[1] 0.46 0.00 0.88 0.00 0.00
## for loop 無しの例
> system.time(print(sum(x/2)))
[1] 0.07 0.02 0.16 0.00 0.00
## これでも最後に一回割る方が数倍早い
> system.time(print(sum(x)/2))
[1] 0.02 0.00 0.05 0.00 0.00
注意:同じ操作を副関数化することはコードの簡潔化に有効で...
> test1 <- function () {
for (i in 1:1000) sum(runif(i))
}
> aux <- function (i) sum(runif(i)) # 副関数化
> test2 <- function () {
for (i in 1:1000) aux(i)
}
> c <- 0; for (i in 1:100) c <- c + system.time(test1())...
[1] 0.1299 0.0000 0.1303 0.0000 0.0000
> c <- 0; for (i in 1:100) c <- c + system.time(test2())...
[1] 0.1319 0.0000 0.1323 0.0000 0.0000 # 少し遅い
* 全体を操作せよ [#if173a98]
狭い部屋で作業するよりも、広い場所で仕事をするほうが当然...
## 1:100 一様乱数10個の平均値を1万個求める
> test1 <- function() {
res <- numeric(10000)
for (i in 1:10000) res[i] <- mean(sample(1...
res
}
> system.time(test1())
[1] 1.87 0.03 3.94 0.00 0.00
> test2 <- function() {
y <- matrix(0, nr=10000, nc=10) # 乱数全体...
for(i in 1:10000) y[i,] <- sample(1:100, 10)
res <- rowSums(y)/10 # 高速な行和...
}
> system.time(test2())
[1] 0.46 0.00 0.91 0.00 0.00
test1 も test2 も,1〜100までの非復元抽出による乱数ですね...
test3 <- function()
{
y <- matrix(sample(1:100, 10000*10, replace=TRUE), 1000...
rowMeans(y) ...
}
system.time(test3())
test3 は,test2 の 40 倍ほどの速度になります。
* リスト変数は高価と心得る [#n169a2ea]
例外として、リスト処理があります。(私の理解不足かもしれま...
> x <- list(rep(0,1000000)) # リストとして処理
> system.time(for (i in 1000000) x[[i]] <- 0)
[1] 0.22 0.02 0.24 0.00 0.00 # それなりに時間がかかる
> x <- numeric(1000000) # ベクトルとして処理
> system.time(for (i in 1000000) x[i] <- 0)
[1] 0 0 0 0 0 # 一瞬
list(rep(0,1000000)) により作られるリストに,x[[1]] ...
for (i in 1000000) x[[i]] <- 0 が遅いのは,i >= 2 の...
> n <- 1000000
> x <- list(rep(0,n)) # リストとして処理
> length(x)
[1] 1 # この時点では...
> system.time(for (i in n) x[[i]] <- 0)
ユーザ システム 経過
0.01 0.00 0.01
> length(x)
[1] 1000000 # この時点では...
# x[[1]][1]〜x[...
# x[[2]]〜x[[10...
やっている内容が違う(しかも,非効率的)ので,時間がかか...
1000000 個の要素を持つリストを作るのは vector("list", 100...
以下の正しいプログラムでは,実行時間はベクトルを使う場合...
x <- vector("list", n)
system.time(for (i in n) x[[i]] <- 0)
* 一つずつ沢山よりも、沢山を一度に [#f20ba136]
R は相当サイズの大きな変数を使ってもめげたりしません。必...
> x <- numeric(10000)
## 標準正規乱数, 1万個を一つずつ
> system.time(for (i in 1:10000) x[i] <- rnorm(1))
[1] 0.44 0.00 0.51 0.00 0.00
## 標準正規乱数, 1万個をいっぺんに
> system.time(x <- rnorm(10000))
[1] 0.01 0.00 0.01 0.00 0.00
> x <- numeric(100000)
## ベルヌイ試行, 10万個を一つずつ
> system.time(for (i in 1:100000) x[i] <- sample(c(0,1),...
[1] 3.87 0.00 3.89 0.00 0.0
## ベルヌイ試行, 10万個を一回に
> system.time(x <- sample(c(0,1), 100000, replace=TRUE))
[1] 0.01 0.01 0.03 0.00 0.00
## 関数呼出しはタダでないことを示す例
> test <- function() {} # 何もしない関数
> system.time(for(i in 1:100000) test()) # それでも呼出...
[1] 0.16 0.00 0.27 0.00 0.00
* 贅沢は素敵だ(花森安治、若い世代には意味不明?) [#ha026d...
上の系になりますが、予めサイズが分かっている変数(ベクトル...
## ベクトルを段々伸ばす
> x <- numeric(0)
> system.time(for (i in 1:10000) x[i] <- 0)
[1] 1.68 0.01 1.69 0.00 0.00
## 最初から必要なだけ入れ物を確保
> x <- numeric(10000)
> system.time(for (i in 1:10000) x[i] <- 0)
[1] 0.09 0.00 0.10 0.00 0.00
# 一様乱数の和が一万を越えるまでの必要個数
> test1 <- function() {
s <- c <- 1
while(s <= 10000) {s <- s + runif(1); c <- ...
print(c(s,c))
}
> system.time(test1())
[1] 10000.14 20093.00
[1] 0.51 0.00 0.67 0.00 0.00
> test2 <- function() {
x <- cumsum(runif(40000)) # 気前良く4万個...
print(sum(x <= 10000) + 1) # x <- 10000 で...
}
> system.time(test2())
[1] 20048
[1] 0.02 0.00 0.01 0.00 0.00
## ベクトルを段々伸ばす例(空いているメモリを必死に探し回...
> system.time({x <- NULL; for (i in 1:10000) x <- c(x,ru...
[1] 1.74 0.00 3.42 0.00 0.00
## 最初に場所を確保
> system.time({x <- numeric(10000); for (i in 1:10000) x...
[1] 0.28 0.00 0.50 0.00 0.00
# 最初に十分大きなベクトル用意し、最後に余分な部分を捨て...
test1 <- function() {
x <- numeric(0) # 空のベクトルから出発
for (i in 1:rnorm(1, m=3000, sd=200)) x[i] <- i
x
}
test2 <- function() {
x <- rep(NA,10000) # NA 値だけの十分大きなベ...
for (i in 1:rnorm(1, m=3000, sd=200)) x[i] <- i
na.omit(x) # NA 値部分を捨てる
}
system.time(x <- test1())
[1] 0.16 0.01 0.17 0.00 0.00
system.time(x <- test2())
[1] 0.03 0.00 0.03 0.00 0.00
length(x) # 実際必要だったベクトル長
[1] 3152
* 論理判断は守銭奴のごとくけちる [#t4f9ae2f]
ループと並ぶ高速化の敵は論理判断です。どんな言語でもこれ...
## 百万個の数のランダムな加減算(工夫で論理判断を掛け算で...
> x <- 1:1000000
> y <- sample(c(TRUE, FALSE), 1000000, replace = TRUE) #...
> s <- 0; system.time(for (i in 1:1000000) if (y[i]) s <...
[1] 5.99 0.01 6.01 0.00 0.00
> system.time(s <- sum((2*y-1)*x)) # 工夫で論値判断を無...
[1] 0.21 0.05 0.28 0.00 0.00
また abs() 関数等はいわば関数自身が論理判断を内蔵していま...
裸々な論理判断を無くすことができます。
また if, while 文はベクトル化されていない稀な構文の例です...
## 混合正規分布乱数一万個を生成
> x <- rnorm(10000) # N(0,1) 乱数一万個
> y <- rnorm(10000, sd = 2, mean= 1) # N(1,2^2) 乱数一万個
> w <- numeric(10000) # 結果をいれるベク...
> test1 <- function(){ # if 文を使う素朴な...
for (i in 1:10000)
if (runif(1)< 0.35) w[i] <- x[i] else w[i...
w
}
> system.time(test1())
[1] 0.51 0.00 0.52 0.00 0.00
> system.time(w <- ifelse(runif(10000)<0.35, x,y)) # ife...
[1] 0.02 0.00 0.01 0.00 0.00
> system.time({p <- (runif(10000)<0.35); w <- p*x+(1-p)*...
[1] 0.01 0.00 0.01 0.00 0.00
データの順序を問題にしないのなら,パラメータの異なる複数...
以下の方法は,上の例の掛け算を利用する方法(三番目)より...
system.time({r <- rbinom(1, n, 0.35); w3 <- c(rnorm(r), ...
* ベクトルは添字で操作せず、(論理)添字集合で操作する [#kb...
ベクトルの部分ベクトルを x[3] の如く、個々の成分で操作す...
x[x < 0] # x の負の要素だけからなるベクトル
x[0 < x & x < 1] # 区間 (0,1) に入る要素からなるベクトル
x[x == 0] # 値が 0 に等しい要素からなるベクトル
x[x != NA] # 欠損値を取り除いたベクトル
x[x %% 3 == 0] # 3 の倍数からなる要素のベクトル
x[y == 0] # y の 0 の要素に対応する x の要素からなるベク...
残念なことに,欠損値が絡むと,上の例のはすべて(!)うま...
四番目以外は,要素に NA がなければちゃんと動く。しかし,N...
> (x <- c(-2, 0, 3, NA, 9, 0.4, 5, 0))
[1] -2.0 0.0 3.0 NA 9.0 0.4 5.0 0.0
# 一番目
> x[x < 0]
[1] -2 NA
# 二番目
> x[0 < x & x < 1]
[1] NA 0.4
# 三番目
> x[x == 0]
[1] 0 NA 0
# 四番目
> x[x != NA]
[1] NA NA NA NA NA NA NA NA # さすがに予想外の結果だ...
# 五番目
> x[x %% 3 == 0]
[1] 0 3 NA 9 0
# 六番目
> (y <- c(NA, 1, 0, 1, 0, 1, 0, 1))
[1] NA 1 0 1 0 1 0 1
> x[y == 0]
[1] NA 3 9 5
欠損値があっても正しく機能するようにするには,subset 関数...
> (x <- c(-2, 0, 3, NA, 9, 0.4, 5, 0))
[1] -2.0 0.0 3.0 NA 9.0 0.4 5.0 0.0
> # 一番目
> subset(x, x < 0)
[1] -2
> # 二番目
> subset(x, 0 < x & x < 1)
[1] 0.4
> # 三番目
> subset(x, x == 0)
[1] 0 0
> # 四番目
> subset(x, !is.na(x))
[1] -2.0 0.0 3.0 9.0 0.4 5.0 0.0
> # または
> x[!is.na(x)]
[1] -2.0 0.0 3.0 9.0 0.4 5.0 0.0
> # 五番目
> subset(x, x %% 3 == 0)
[1] 0 3 9 0
> # 六番目
> (y <- c(NA, 1, 0, 1, 0, 1, 0, 1))
[1] NA 1 0 1 0 1 0 1
> subset(x, y == 0)
[1] 3 9 5
教訓:欠損値があるときの挙動もちゃんと確認しておこう(実...
次の性質も覚えておくと役にたつことがあります(参考例クイッ...
x <- runif(10)
y <- x[x < 0] # 長さ0のベクトル(空集合)になる
all.equal(x, c(x,y)) # 長さ0のベクトルを付け加えても変化...
TRUE
# 論理値 TRUE, FALSE は数が要求される局面では整数 1,0 に...
> TRUE + TRUE +FALSE # 1 + 1 + 0 と解釈される
[1] 2
> sum(c(TRUE, TRUE, FALSE, TRUE))
[1] 3
> FALSE * 0.5 # 0 * 0.5 と解釈される
[1] 0
> x <- 0:5
> x < 3 # 論理値ベクトルになる
[1] TRUE TRUE TRUE FALSE FALSE FALSE
> sum(x < 3) # 3 未満の x の要素の数
[1] 3
* 返り値 [#g2273a6d]
これは高速化という意味ではなく、コードの簡潔化という意味...
# 代入し、そして和を求める
x <- y
z <- sum(x)
# 一行で書けば(x に y を代入し、その暗黙の返り値、つまり...
z <- sum(x <- y)
y <- z
x <- exp(y)
# 一行で書けば
x <- exp(y <- z)
# 実行時間は少し遅くなるらしい
> system.time(for(i in 1:10000) {z <- runif(1000); y <- ...
[1] 6.27 0.00 6.28 0.00 0.00
> system.time(for(i in 1:10000) {x <- exp(y <- (z <- run...
[1] 6.46 0.00 6.47 0.00 0.00
ほとんど誤差範囲で,むしろ後者の方が速いのでは?@rem:2010...
> n <- 100000
> system.time(for(i in 1:n) {z <- runif(1000); y <- z^2;...
ユーザ システム 経過
9.788 0.815 10.558
> system.time(for(i in 1:n) {x <- exp(y <- (z <- runif(1...
ユーザ システム 経過
9.715 0.827 10.472
* 問題を変形する [#c091531e]
R に助けてもらうことばかり考えず、R を助けてあげることも...
* デバッグしやすさを最初から考慮する [#t18a8ffe]
経験によれば次の近似的不等式が成り立ちます:
デバッグに必要な時間 >= (プログラミングに要するトータル...
ですから最初からデバッグしやすいようにコーディングすべき...
これには決め手はありませんが、いくつかのコツはあります。
-多重ループは混乱しやすい。ループが閉じるところにコメント...
-(日本語の)コメントを随所に置く
-分かりやすい、そして他と紛らわしくない変数名を使う。特に...
-永続付値演算子 <<- はしばしば便利ですが、何をしているの...
-プログラムを一連の関数に分割する。特に補助的な(しかし本...
-プログラムが求める結果を確かに計算していることを確認でき...
COLOR(red){誤つは人の常、デバッグは世の常、そして結果の正...
* 人生という長期的スパンで最適化を考える [#f78fa9ae]
高速化はあくまで手段であって、最終目的ではありません。高...
* 違いのわかる(気になる)人向け [#p210557e]
- 頻繁に使う定数は変数に代入し、変数として引用する。COLOR...
> system.time(for (i in 1:1000000) sample(1:52))
[1] 41.95 0.31 84.71 0.00 0.00
> a <- 1:52
> system.time(for (i in 1:1000000) sample(a)) # 少しは早い
[1] 37.29 0.00 74.63 0.00 0.00
- 既存変数を再利用(変数の構造・サイズが変わる場合はどうか...
> test1 <- function() {x <- runif(1000000); y <- x^2} # ...
> system.time(test1())
[1] 0.62 0.04 0.67 0.00 0.00
> test2 <- function() {x <- runif(1000000); x <- x^2} # ...
> system.time(test2())
[1] 0.48 0.03 0.50 0.00 0.00
- 永続付値(他の環境中の変数への付値)は手間がかかる。COL...
> test1 <- function(){x <- runif(10000)} # 自前の環境中...
> test2 <- function(){x <<- runif(10000)} # 親環境中の x...
> rm(x); c = 0; for(i in 1:100) c <- c + system.time(tes...
[1] 0.0015 0.0000 0.0020 0.0000 0.0000
> x
Error: Object "x" not found # 変数 x は関...
> x <- numeric(10000); c = 0; for(i in 1:100) c <- c + s...
[1] 0.0018 0.0000 0.0021 0.0000 0.0000
> x[1:5] # 当然 x は存在
[1] 0.02132324 0.36266310 0.50504673 0.89662908 0.67079898
- 変数初期化のコツ。同一のベクトル、配列変数を全要素 0 で...
> x=1:5
> system.time(for(i in 1:10^6) y <- numeric(5))
[1] 6.22 0.03 6.34 0.00 0.00
> system.time(for(i in 1:10^6) y <- 0*x)
[1] 2.94 0.01 3.00 0.00 0.00
> system.time(for(i in 1:10^6) y <- x-x)
[1] 2.58 0.01 2.75 0.00 0.00
> x=matrix(1:16, nc=4, nr=4)
> system.time(for(i in 1:10^4) y <- matrix(0, nc=4, nr=...
[1] 0.35 0.00 0.38 0.00 0.00
> system.time(for(i in 1:10^4) y <- 0*x)
[1] 0.04 0.01 0.05 0.00 0.00
> system.time(for(i in 1:10^4) y <- x-x)
[1] 0.04 0.00 0.04 0.00 0.00
-行列・配列の添字に関するCOLOR(red){ループは順序が大事}、...
x <- array(1:10^6, c(100, 100, 100))
ijk <- function() { # 添字の順にアクセス
for (i in 1:100) for (j in 1:100) for (k in 1:1...
}
ikj <- function() { # こんなことをする人はいないだろうが
for (i in 1:100) for (j in 1:100) for (k in 1:1...
}
kji <- function() { # 添字の逆順にアクセス
for (i in 1:100) for (j in 1:100) for (k in 1:1...
}
e <- function() { # 添字を全く使わない例
for (e in x) e
}
> system.time(ijk())
[1] 3.71 0.00 3.72 0.00 0.00
> system.time(ikj())
[1] 3.56 0.00 3.58 0.00 0.00
> system.time(kji())
[1] 3.26 0.00 3.27 0.00 0.00
> system.time(e())
[1] 0.26 0.00 0.28 0.00 0.00
* 補遺、それでもまだ遅いと文句の多い人は [#z79a5f55]
- COLOR(blue){金持なら:} CPU 速度の早い機械を買う、メモ...
- COLOR(blue){金がなければ:} 線形関数数値ライブラリ BLAS...
- COLOR(blue){環境に恵まれれていれば:} 周りの R wizard ...
- COLOR(blue){Tierney 氏のバイトコンパイル関数}を使ってみ...
- COLOR(blue){プログラミングに堪能なら:} C, FORTRAN サブ...
- COLOR(blue){頭に自信があれば:} 計算機を使わず、頭を使...
- COLOR(blue){上のいずれにも該当しなければ:} さっさとあ...
~
以上を参考に R プログラミングに精進して下さい。いつの日か...
* コード最適化の具体例 [#x2ef9ff6]
以下コード最適化の具体例を初心者への参考にいくつか挙げた...
** (1) r-help 記事より [[Rコードの最適化(初心者用メモ)]...
** (2) Q&A 記事より [[Rコード最適化例:空間点パターンのメ...
** (3) 「The R Book」 中の例を元にして [[Rコードの最適化...
** (4) 「工学のためのデータサイエンス入門」中の例を元にし...
** (5) [[Rコードの最適化例:ベクトルはベクトルとして操作...
** (6) [[Rコードの最適化例:配列はベクトルとして操作する]...
** (7) [[Rコードの最適化例:レスリー行列による個体群成長]...
** (8) [[Rコードの最適化例:混合正規乱数の発生コード]] 舟...
** (9) [[Rコードの最適化例:行が同じ数かどうかの判定]] r-...
** (10) [[Rコードの最適化例:行列のクロス積]] r-help 記事...
** (11) 行列の成分毎の積 r-help 記事より(2005.04.17) [#...
行列と1列行列の成分毎の積(行列としての積でなく)は、行列...
> mm <- matrix(1, 1000, 1000)
> ee <- matrix(1:100,nc=1)
> system.time(mm*ee[,], TRUE) # 行列 ee を掛ける
[1] 0.26 0.02 0.28 NA NA
> system.time(mm*c(ee), TRUE) # ee をベクトルとした上...
[1] 0.07 0.00 0.07 NA NA
おもしろい現象がある。R を起動した後最初に実行するときと...
なお,ee のサイズが 100 なのは間違いかな?@rem:2010/05/20
# 一回目
> mm <- matrix(1, 1000, 1000)
> ee <- matrix(1:100,nc=1)
> system.time(mm*ee[,], TRUE) # 行列 ee を掛ける
ユーザ システム 経過
0.033 0.006 0.039
> system.time(mm*c(ee), TRUE) # ee をベクトルとした上...
ユーザ システム 経過
0.006 0.006 0.013
# 二回目
> mm <- matrix(1, 1000, 1000)
> ee <- matrix(1:100,nc=1)
> system.time(mm*ee[,], TRUE) # 行列 ee を掛ける
ユーザ システム 経過
0.007 0.006 0.012
> system.time(mm*c(ee), TRUE) # ee をベクトルとした上...
ユーザ システム 経過
0.006 0.007 0.013
なお,このときの R のバージョンがいくつかによりますが(R-...
> class(ee[,]) # ee[,] は,ベクトル!!
[1] "integer"
> class(c(ee))
[1] "integer"
> class(ee) # ee は行列なので,
[1] "matrix"
> system.time(mm*ee, TRUE) # これは,エラーになる
以下にエラー mm * ee : 適切な配列ではありません
Timing stopped at: 0 0 0
* コメント、「俺ならこうする」等ありましたら以下にどうぞ ...
-RjpWiki 一周年記念コンテンツにふさわしい内容ではないでし...
-因みに論理判断が遅いのは、判断の結果次第で次に行う処理が...
-Rの持つ組み込みベクトル化機能を使うと速いのは、「メモリ...
-計算機の記憶領域は階層化されている。メモリは小さいがデー...
-R のライブラリは FORTRAN で書かれているのだろうか。~
配列の格納法(メモリ上の配置)から考えると,C とは異なり...
a <- function()
{
x <- matrix(1:100000, nr=20000, nc=5)
for (loop in 1:50) {
for (i in 1:20000) {
for (j in 1:5) {
x[i,j]
}
}
}
}
b <- function()
{
x <- matrix(1:100000, nr=20000, nc=5)
for (loop in 1:50) {
for (j in 1:5) {
for (i in 1:20000) {
x[i,j]
}
}
}
}
system.time(a())
system.time(b())
> system.time(a())
[1] 31.49 3.27 46.92 0.00 0.00
> system.time(b())
[1] 26.09 2.85 38.93 0.00 0.00
追試希望。 -- &new{2004-06-22 (火) 19:27:10};
-確かに,y <- 0*x は速いですね。y <- x-x の方がもう少しだ...
- 1で初期化する場合は0*x+1よりx^0が高速。さらに論理値で良...
- 行列の行や列に対する演算には、rowMeansなどを使う方法とa...
- そういうことは,オンラインヘルプにちゃんと書いてありま...
- sample(1:n,m) やa<-1:n; sample(a,m)より sample.int(n,m)...
- その差は,ノミの金玉くらいだ -- &new{2013-09-20 (金) 1...
> library(rbenchmark)
> benchmark(sample(1000, 1e6, replace=TRUE), sample.int(...
test replications e...
2 sample.int(1000, 1e+06, replace = TRUE) 100 ...
1 sample(1000, 1e+06, replace = TRUE) 100 ...
なぜそうなるかは,sample 関数を表示してみると分かる。つま...
> sample
function (x, size, replace = FALSE, prob = NULL)
{
if (length(x) == 1L && is.numeric(x) && x >= 1) {
if (missing(size))
size <- x
sample.int(x, size, replace, prob)
}
else {
if (missing(size))
size <- length(x)
x[sample.int(length(x), size, replace, prob)]
}
}
else 節はどういうことかというと,第1引数にベクトルを指定...
> library(rbenchmark)
> benchmark(sample(1:1000, 1e6, replace=TRUE), sample(10...
test replications e...
3 sample.int(1000, 1e+06, replace = TRUE) 100 ...
1 sample(1:1000, 1e+06, replace = TRUE) 100 ...
2 sample(1000, 1e+06, replace = TRUE) 100 ...
#comment
ページ名: