このスレッドでは、よくある質問とその回答をすべてここに含めようとしています。これが誰かに役立つことを願っています。
一般的な質問:r
オブジェクトからn
オブジェクトのシーケンスを生成する方法?
合計で2^3=8
このタイプの質問。
[更新]
Josh O'Brienは、8つの質問は 12通りの方法 に関連していると示唆しています。実際、「明確な」質問は12通りの方法で含まれていますが、「明確でない」質問は含まれていません。とにかく、ここで8つの質問を12通りの方法と比較するのは興味深いことです。詳細については、コメントを参照してください。
[〜#〜] edit [〜#〜]:より効率的なパッケージを使用するように回答を更新しました arrangements
arrangement
の使用を開始するarrangements には、順列と組み合わせのための効率的なジェネレーターとイテレーターが含まれています。 arrangements
は、類似の種類の既存のパッケージのほとんどよりも優れていることが実証されています。いくつかのベンチマークが見つかりました here 。
上記の質問に対する回答です
_# 1) combinations: without replacement: distinct items
combinations(5, 2)
[,1] [,2]
[1,] 1 2
[2,] 1 3
[3,] 1 4
[4,] 1 5
[5,] 2 3
[6,] 2 4
[7,] 2 5
[8,] 3 4
[9,] 3 5
[10,] 4 5
# 2) combinations: with replacement: distinct items
combinations(5, 2, replace=TRUE)
[,1] [,2]
[1,] 1 1
[2,] 1 2
[3,] 1 3
[4,] 1 4
[5,] 1 5
[6,] 2 2
[7,] 2 3
[8,] 2 4
[9,] 2 5
[10,] 3 3
[11,] 3 4
[12,] 3 5
[13,] 4 4
[14,] 4 5
[15,] 5 5
# 3) combinations: without replacement: non distinct items
combinations(x = c("a", "b", "c"), freq = c(2, 1, 1), k = 2)
[,1] [,2]
[1,] "a" "a"
[2,] "a" "b"
[3,] "a" "c"
[4,] "b" "c"
# 4) combinations: with replacement: non distinct items
combinations(x = c("a", "b", "c"), k = 2, replace = TRUE) # as `freq` does not matter
[,1] [,2]
[1,] "a" "a"
[2,] "a" "b"
[3,] "a" "c"
[4,] "b" "b"
[5,] "b" "c"
[6,] "c" "c"
# 5) permutations: without replacement: distinct items
permutations(5, 2)
[,1] [,2]
[1,] 1 2
[2,] 1 3
[3,] 1 4
[4,] 1 5
[5,] 2 1
[6,] 2 3
[7,] 2 4
[8,] 2 5
[9,] 3 1
[10,] 3 2
[11,] 3 4
[12,] 3 5
[13,] 4 1
[14,] 4 2
[15,] 4 3
[16,] 4 5
[17,] 5 1
[18,] 5 2
[19,] 5 3
[20,] 5 4
# 6) permutations: with replacement: distinct items
permutations(5, 2, replace = TRUE)
[,1] [,2]
[1,] 1 1
[2,] 1 2
[3,] 1 3
[4,] 1 4
[5,] 1 5
[6,] 2 1
[7,] 2 2
[8,] 2 3
[9,] 2 4
[10,] 2 5
[11,] 3 1
[12,] 3 2
[13,] 3 3
[14,] 3 4
[15,] 3 5
[16,] 4 1
[17,] 4 2
[18,] 4 3
[19,] 4 4
[20,] 4 5
[21,] 5 1
[22,] 5 2
[23,] 5 3
[24,] 5 4
[25,] 5 5
# 7) permutations: without replacement: non distinct items
permutations(x = c("a", "b", "c"), freq = c(2, 1, 1), k = 2)
[,1] [,2]
[1,] "a" "a"
[2,] "a" "b"
[3,] "a" "c"
[4,] "b" "a"
[5,] "b" "c"
[6,] "c" "a"
[7,] "c" "b"
# 8) permutations: with replacement: non distinct items
permutations(x = c("a", "b", "c"), k = 2, replace = TRUE) # as `freq` doesn't matter
[,1] [,2]
[1,] "a" "a"
[2,] "a" "b"
[3,] "a" "c"
[4,] "b" "a"
[5,] "b" "b"
[6,] "b" "c"
[7,] "c" "a"
[8,] "c" "b"
[9,] "c" "c"
_
既存のパッケージと比較してarrangements
を使用する利点はほとんどありません。
統合フレームワーク:メソッドごとに異なるパッケージを使用する必要はありません。
とても効率的です。ベンチマークについては https://randy3k.github.io/arrangements/articles/benchmark.html を参照してください。
メモリ効率がよく、13個すべてを生成できます。 1から13の順列は、既存のパッケージがマトリックスサイズの制限のためにそうすることに失敗します。イテレータのgetnext()
メソッドを使用すると、ユーザーは配置を1つずつ取得できます。
生成された配置は、一部のユーザーにとって望ましい可能性がある辞書順です。
以下では、組み合わせと順列を生成する機能を備えたパッケージを調べます。パッケージを省略した場合は、ご容赦ください。コメントを残すか、この投稿を編集してください。
分析の概要:
始める前に、組み合わせ/順列withが、選択された個別アイテムと非個別アイテムの置き換えmを一度に置き換えることに注意してください同等です。これはそうです、私たちが交換をするとき、それは特定ではありません。したがって、特定の要素が最初に何回発生しても、出力にはその要素のインスタンスが1からm回繰り返されます。
gtools
v 3.8.1combinat
v 0.0-8multicool
v 0.1-10partitions
v 1.9-19RcppAlgos
v 2.0.1(私は作成者です)arrangements
v 1.1.0gRbase
v 1.8-3permute
、permutations
、または_gRbase::aperm/ar_perm
_は、これらのタイプの問題を攻撃することを意図していないため、含めませんでした。
| ---------------------------------------[ 〜#〜]概要[〜#〜]------------------------------- ------
_|_______________| gtools | combinat | multicool | partitions |
| comb rep | Yes | | | |
| comb NO rep | Yes | Yes | | |
| perm rep | Yes | | | |
| perm NO rep | Yes | Yes | Yes | Yes |
| perm multiset | | | Yes | |
| comb multiset | | | | |
|accepts factors| | Yes | | |
| m at a time | Yes | Yes/No | | |
|general vector | Yes | Yes | Yes | |
| iterable | | | Yes | |
|parallelizable | | | | |
| big integer | | | | |
|_______________| iterpc | arrangements | RcppAlgos | gRbase |
| comb rep | Yes | Yes | Yes | |
| comb NO rep | Yes | Yes | Yes | Yes |
| perm rep | Yes | Yes | Yes | |
| perm NO rep | Yes | Yes | Yes | * |
| perm multiset | Yes | Yes | Yes | |
| comb multiset | Yes | Yes | Yes | |
|accepts factors| | Yes | Yes | |
| m at a time | Yes | Yes | Yes | Yes |
|general vector | Yes | Yes | Yes | Yes |
| iterable | | Yes | Partially | |
|parallelizable | | Yes | Yes | |
| big integer | | Yes | | |
_
タスク_m at a time
_および_general vector
_は、結果を生成する機能を参照します "m一度に"(-mが長さより小さい場合)ベクトルの)および_1:n
_とは対照的に「一般的なベクトル」を再配置します。実際には、一般的に一般的なベクトルの再配置を見つけることに関心があるため、以下のすべての検査はこれを反映します(可能な場合)。
すべてのベンチマークは、3つの異なるセットアップで実行されました。
リストされた結果は、セットアップ#1(つまり、MBPro)から取得されました。他の2つのシステムの結果は同様でした。また、gc()
は定期的に呼び出され、すべてのメモリが使用可能であることを確認します(_?gc
_を参照)。
最初に、置換なしの組み合わせを選択しますmを一度に調べます。
RcppAlgos
combinat
(またはutils
)gtools
arrangements
gRbase
方法:
_library(RcppAlgos)
library(arrangements)
library(microbenchmark)
options(digits = 4)
set.seed(13)
testVector1 <- sort(sample(100, 17))
m <- 9
t1 <- comboGeneral(testVector1, m) ## returns matrix with m columns
t3 <- combinat::combn(testVector1, m) ## returns matrix with m rows
t4 <- gtools::combinations(17, m, testVector1) ## returns matrix with m columns
identical(t(t3), t4) ## must transpose to compare
#> [1] TRUE
t5 <- combinations(testVector1, m)
identical(t1, t5)
#> [1] TRUE
t6 <- gRbase::combnPrim(testVector1, m)
identical(t(t6)[do.call(order, as.data.frame(t(t6))),], t1)
#> [1] TRUE
_
基準:
_microbenchmark(cbRcppAlgos = comboGeneral(testVector1, m),
cbGRbase = gRbase::combnPrim(testVector1, m),
cbGtools = gtools::combinations(17, m, testVector1),
cbCombinat = combinat::combn(testVector1, m),
cbArrangements = combinations(17, m, testVector1),
unit = "relative")
#> Unit: relative
#> expr min lq mean median uq max neval
#> cbRcppAlgos 1.064 1.079 1.160 1.012 1.086 2.318 100
#> cbGRbase 7.335 7.509 5.728 6.807 5.390 1.608 100
#> cbGtools 426.536 408.807 240.101 310.848 187.034 63.663 100
#> cbCombinat 97.756 97.586 60.406 75.415 46.391 41.089 100
#> cbArrangements 1.000 1.000 1.000 1.000 1.000 1.000 100
_
ここで、置換を選択した組み合わせmを一度に調べます。
RcppAlgos
gtools
arrangements
方法:
_library(RcppAlgos)
library(arrangements)
library(microbenchmark)
options(digits = 4)
set.seed(97)
testVector2 <- sort(rnorm(10))
m <- 8
t1 <- comboGeneral(testVector2, m, repetition = TRUE)
t3 <- gtools::combinations(10, m, testVector2, repeats.allowed = TRUE)
identical(t1, t3)
#> [1] TRUE
## arrangements
t4 <- combinations(testVector2, m, replace = TRUE)
identical(t1, t4)
#> [1] TRUE
_
基準:
_microbenchmark(cbRcppAlgos = comboGeneral(testVector2, m, TRUE),
cbGtools = gtools::combinations(10, m, testVector2, repeats.allowed = TRUE),
cbArrangements = combinations(testVector2, m, replace = TRUE),
unit = "relative")
#> Unit: relative
#> expr min lq mean median uq max neval
#> cbRcppAlgos 1.000 1.000 1.000 1.000 1.000 1.00000 100
#> cbGtools 384.990 269.683 80.027 112.170 102.432 3.67517 100
#> cbArrangements 1.057 1.116 0.618 1.052 1.002 0.03638 100
_
最初に、置換なしの順列を選択しますmを一度に調べます。
RcppAlgos
gtools
arrangements
方法:
_library(RcppAlgos)
library(arrangements)
library(microbenchmark)
options(digits = 4)
set.seed(101)
testVector3 <- as.integer(c(2, 3, 5, 7, 11, 13, 17, 19, 23, 29))
## RcppAlgos... permuteGeneral same as comboGeneral above
t1 <- permuteGeneral(testVector3, 6)
## gtools... permutations same as combinations above
t3 <- gtools::permutations(10, 6, testVector3)
identical(t1, t3)
#> [1] TRUE
## arrangements
t4 <- permutations(testVector3, 6)
identical(t1, t4)
#> [1] TRUE
_
基準:
_microbenchmark(cbRcppAlgos = permuteGeneral(testVector3, 6),
cbGtools = gtools::permutations(10, 6, testVector3),
cbArrangements = permutations(testVector3, 6),
unit = "relative")
#> Unit: relative
#> expr min lq mean median uq max neval
#> cbRcppAlgos 1.079 1.027 1.106 1.037 1.003 5.37 100
#> cbGtools 158.720 92.261 85.160 91.856 80.872 45.39 100
#> cbArrangements 1.000 1.000 1.000 1.000 1.000 1.00 100
_
次に、一般的なベクトルで置換せずに順列を調べます(すべての順列を返します)。
RcppAlgos
gtools
combinat
multicool
arrangements
方法:
_library(RcppAlgos)
library(arrangements)
library(microbenchmark)
options(digits = 4)
set.seed(89)
testVector3 <- as.integer(c(2, 3, 5, 7, 11, 13, 17, 19, 23, 29))
testVector3Prime <- testVector3[1:7]
## For RcppAlgos, & gtools (see above)
## combinat
t4 <- combinat::permn(testVector3Prime) ## returns a list of vectors
## convert to a matrix
t4 <- do.call(rbind, t4)
## multicool.. we must first call initMC
t5 <- multicool::allPerm(multicool::initMC(testVector3Prime)) ## returns a matrix with n columns
all.equal(t4[do.call(order,as.data.frame(t4)),],
t5[do.call(order,as.data.frame(t5)),])
#> [1] TRUE
_
基準:
_microbenchmark(cbRcppAlgos = permuteGeneral(testVector3Prime, 7),
cbGtools = gtools::permutations(7, 7, testVector3Prime),
cbCombinat = combinat::permn(testVector3Prime),
cbMulticool = multicool::allPerm(multicool::initMC(testVector3Prime)),
cbArrangements = permutations(x = testVector3Prime, k = 7),
unit = "relative")
#> Unit: relative
#> expr min lq mean median uq max neval
#> cbRcppAlgos 1.152 1.275 0.7508 1.348 1.342 0.3159 100
#> cbGtools 965.465 817.645 340.4159 818.137 661.068 12.7042 100
#> cbCombinat 280.207 236.853 104.4777 238.228 208.467 9.6550 100
#> cbMulticool 2573.001 2109.246 851.3575 2039.531 1638.500 28.3597 100
#> cbArrangements 1.000 1.000 1.0000 1.000 1.000 1.0000 100
_
ここで、_1:n
_の代わりに置換を調べます(すべての置換を返します)。
RcppAlgos
gtools
combinat
multicool
partitions
arrangements
方法:
_library(RcppAlgos)
library(arrangements)
library(microbenchmark)
options(digits = 4)
set.seed(89)
t1 <- partitions::perms(7) ## returns an object of type 'partition' with n rows
identical(t(as.matrix(t1)), permutations(7,7))
#> [1] TRUE
_
基準:
_microbenchmark(cbRcppAlgos = permuteGeneral(7, 7),
cbGtools = gtools::permutations(7, 7),
cbCombinat = combinat::permn(7),
cbMulticool = multicool::allPerm(multicool::initMC(1:7)),
cbPartitions = partitions::perms(7),
cbArrangements = permutations(7, 7),
unit = "relative")
#> Unit: relative
#> expr min lq mean median uq max
#> cbRcppAlgos 1.235 1.429 1.412 1.503 1.484 1.720
#> cbGtools 1152.826 1000.736 812.620 939.565 793.373 499.029
#> cbCombinat 347.446 304.866 260.294 296.521 248.343 284.001
#> cbMulticool 3001.517 2416.716 1903.903 2237.362 1811.006 1311.219
#> cbPartitions 2.469 2.536 2.801 2.692 2.999 2.472
#> cbArrangements 1.000 1.000 1.000 1.000 1.000 1.000
#> neval
#> 100
#> 100
#> 100
#> 100
#> 100
#> 100
_
最後に、置換による置換を調べます。
RcppAlgos
iterpc
gtools
arrangements
方法:
_library(RcppAlgos)
library(arrangements)
library(microbenchmark)
options(digits = 4)
set.seed(34)
testVector3 <- as.integer(c(2, 3, 5, 7, 11, 13, 17, 19, 23, 29))
t1 <- permuteGeneral(testVector3, 5, repetition = TRUE)
t3 <- gtools::permutations(10, 5, testVector3, repeats.allowed = TRUE)
t4 <- permutations(x = testVector3, k = 5, replace = TRUE)
_
この次のベンチマークは、これまでの結果を考えると少し意外です。
_microbenchmark(cbRcppAlgos = permuteGeneral(testVector3, 5, TRUE),
cbGtools = gtools::permutations(10, 5, testVector3, repeats.allowed = TRUE),
cbArrangements = permutations(x = testVector3, k = 5, replace = TRUE),
unit = "relative")
#> Unit: relative
#> expr min lq mean median uq max neval
#> cbRcppAlgos 1.106 0.9183 1.200 1.030 1.063 1.701 100
#> cbGtools 2.426 2.1815 2.068 1.996 2.127 1.367 100
#> cbArrangements 1.000 1.0000 1.000 1.000 1.000 1.000 100
_
これはタイプミスではありません... _gtools::permutations
_は、他のコンパイル済み関数とほぼ同じくらい高速です。 _gtools::permutations
_のソースコードをチェックすることをお勧めします(R
またはそれ以外の場合)。
最初に、マルチセットの組み合わせを調べます。
RcppAlgos
arrangements
マルチセットの組み合わせ/順列を見つけるには、RcppAlgos
を使用してfreqs
引数を使用し、ソースベクトルv
の各要素が繰り返される回数を指定します。
_library(RcppAlgos)
library(arrangements)
library(microbenchmark)
options(digits = 4)
set.seed(496)
myFreqs <- sample(1:5, 10, replace = TRUE)
## This is how many times each element will be repeated
myFreqs
#> [1] 2 4 4 5 3 2 2 2 3 4
testVector4 <- as.integer(c(1, 2, 3, 5, 8, 13, 21, 34, 55, 89))
t1 <- comboGeneral(testVector4, 12, freqs = myFreqs)
t3 <- combinations(freq = myFreqs, k = 12, x = testVector4)
identical(t1, t3)
#> [1] TRUE
_
基準:
_microbenchmark(cbRcppAlgos = comboGeneral(testVector4, 12, freqs = myFreqs),
cbArrangements = combinations(freq = myFreqs, k = 12, x = testVector4),
unit = "relative")
#> Unit: relative
#> expr min lq mean median uq max neval
#> cbRcppAlgos 1.000 1.000 1.000 1.000 1.000 1.000 100
#> cbArrangements 1.254 1.221 1.287 1.259 1.413 1.173 100
_
mを一度に選択したマルチセットの順列の場合、次のようになります。
RcppAlgos
arrangements
方法:
_library(RcppAlgos)
library(arrangements)
library(microbenchmark)
options(digits = 4)
set.seed(8128)
myFreqs <- sample(1:3, 5, replace = TRUE)
testVector5 <- sort(runif(5))
myFreqs
#> [1] 2 2 2 1 3
t1 <- permuteGeneral(testVector5, 7, freqs = myFreqs)
t3 <- permutations(freq = myFreqs, k = 7, x = testVector5)
identical(t1, t3)
#> [1] TRUE
_
基準:
_microbenchmark(cbRcppAlgos = permuteGeneral(testVector5, 7, freqs = myFreqs),
cbArrangements = permutations(freq = myFreqs, k = 7, x = testVector5),
unit = "relative")
#> Unit: relative
#> expr min lq mean median uq max neval
#> cbRcppAlgos 1.461 1.327 1.282 1.177 1.176 1.101 100
#> cbArrangements 1.000 1.000 1.000 1.000 1.000 1.000 100
_
すべての順列を返すマルチセットの順列の場合、次のようになります。
RcppAlgos
multicool
arrangements
方法:
_library(RcppAlgos)
library(arrangements)
library(microbenchmark)
options(digits = 4)
set.seed(8128)
myFreqs2 <- c(2,1,2,1,2)
testVector6 <- (1:5)^3
## For multicool, you must have the elements explicitly repeated
testVector6Prime <- rep(testVector6, times = myFreqs2)
t3 <- multicool::allPerm(multicool::initMC(testVector6Prime))
## for comparison
t1 <- permuteGeneral(testVector6, freqs = myFreqs2)
identical(t1[do.call(order,as.data.frame(t1)),],
t3[do.call(order,as.data.frame(t3)),])
#> [1] TRUE
_
基準:
_microbenchmark(cbRcppAlgos = permuteGeneral(testVector6, freqs = myFreqs2),
cbMulticool = multicool::allPerm(multicool::initMC(testVector6Prime)),
cbArrangements = permutations(freq = myFreqs2, x = testVector6),
unit = "relative")
#> Unit: relative
#> expr min lq mean median uq max neval
#> cbRcppAlgos 1.276 1.374 1.119 1.461 1.39 0.8856 100
#> cbMulticool 2434.652 2135.862 855.946 2026.256 1521.74 31.0651 100
#> cbArrangements 1.000 1.000 1.000 1.000 1.00 1.0000 100
_
gtools
とcombinat
はどちらも、ベクトルの要素を再配置するための確立されたパッケージです。 gtools
を使用すると、さらにいくつかのオプションがあり(上記の概要を参照)、combinat
を使用すると、factors
を再配置できます。 multicool
を使用すると、マルチセットを再配置できます。 partitions
とgRbase
はこの質問の目的のために制限されていますが、パーティションと配列オブジェクトをそれぞれ処理するための非常に効率的な関数が詰め込まれた強力な会社です。
arrangements
layout
引数(_r = row-major
_、_c = column-major
_、および_l = list
_)を介して形式を指定できるようにします。collect
&getnext
などの便利なメソッドを提供します。getnext
を介して_2^31 - 1
_を超える組み合わせ/順列の生成を可能にします。 N.B. RcppAlgos
(_lower/upper
_を介して以下を参照)およびmulticool
(nextPerm
を介して)もこれを実行できます。getnext
と言えば、この関数は、d
引数を利用して特定の数の結果を可能にします。観察する:
_library(arrangements)
icomb <- icombinations(1000, 7)
icomb$getnext(d = 5)
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 1 2 3 4 5 6 7
#> [2,] 1 2 3 4 5 6 8
#> [3,] 1 2 3 4 5 6 9
#> [4,] 1 2 3 4 5 6 10
#> [5,] 1 2 3 4 5 6 11
_
この機能は、いくつかの組み合わせ/順列だけが必要な場合に非常に便利です。従来の方法では、すべての組み合わせ/順列を生成してからサブセットを生成する必要がありました。 _10^17
_を超える結果(つまり、ncombinations(1000, 7, bigz = TRUE)
= 194280608456793000)があるため、前の例は不可能になります。
この機能とarrangements
のジェネレーターの改善により、メモリーに関して非常に効率的になります。
RcppAlgos
upper
のrowCap
引数に類似した引数d
(正式にはgetnext
)があります。観察する:
_library(RcppAlgos)
comboGeneral(1000, 7, upper = 5)
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 1 2 3 4 5 6 7
#> [2,] 1 2 3 4 5 6 8
#> [3,] 1 2 3 4 5 6 9
#> [4,] 1 2 3 4 5 6 10
#> [5,] 1 2 3 4 5 6 11
_
2.0.0
_以降、lower
と呼ばれる引数があり、特定の組み合わせ/順列で生成を開始できます。これにより、並列化が適切に設定され、チャンクが独立して生成されるため、_2^31 - 1
_を超える高速生成が可能になります。60億を超える組み合わせの並列例:
_system.time(parallel::mclapply(seq(1,6397478649,4390857), function(x) {
a <- comboGeneral(25, 15, freqs = c(rep(1:5, 5)), lower = x, upper = x + 4390856)
## do something
x
}, mc.cores = 7))
#> user system elapsed
#> 510.623 140.970 109.496
_
各パッケージがどのようにスケーリングするのか疑問に思っている場合は、各パッケージが1億を超える結果を生成できる速さを測定するこの最後の例を残します(NB _gtools::combinations
_はエラーをスローするため、ここでは省略します:_evaluation nested too deeply...
_)。また、_combinat::combn
_から正常に実行できなかったため、combn
パッケージから明示的にutils
を呼び出しています。これら2つのメモリ使用量の違いは、ごくわずかしか異なることを考えると、かなり奇妙です(「作成者」セクションの_?utils::combn
_を参照)。
観察する:
_library(RcppAlgos)
library(arrangements)
library(microbenchmark)
options(digits = 4)
set.seed(2187)
testVector7 <- sort(sample(10^7, 10^3))
system.time(utils::combn(testVector7, 3))
#> user system elapsed
#> 179.956 5.687 187.159
system.time(RcppAlgos::comboGeneral(testVector7, 3))
#> user system elapsed
#> 1.136 0.758 1.937
system.time(arrangements::combinations(x = testVector7, k = 3))
#> user system elapsed
#> 1.963 0.930 2.910
system.time(RcppAlgos::permuteGeneral(testVector7[1:500], 3))
#> user system elapsed
#> 1.095 0.631 1.738
system.time(arrangements::permutations(x = testVector7[1:500], k = 3))
#> user system elapsed
#> 1.399 0.584 1.993
_
comboGeneral
と_arrangements::combinations
_を実行すると、gc
を呼び出す前にメモリがほぼ2 GBジャンプします。これは#rows * #nols * bytesPerCell / 2^30 bytes = choose(1000,3) * 3 * 4 / 2^30 bytes = (166167000 * 3 * 4)/2^30 = 1.857 Gbs
)とほぼ同じです。ただし、combn
を実行すると、メモリの動作が不安定になります(たとえば、16 Gbのメモリすべてを使用することもあれば、2、3 Gbしかスパイクしないこともあります)。これをWindowsセットアップでテストしたところ、クラッシュすることがよくありました。
これは、Rprof
とsummaryRporf
を使用して確認できます。観察する:
_Rprof("RcppAlgos.out", memory.profiling = TRUE)
t1 <- RcppAlgos::comboGeneral(testVector7, 3)
Rprof(NULL)
summaryRprof("RcppAlgos.out", memory = "both")$by.total
total.time total.pct mem.total self.time self.pct
"CombinatoricsRcpp" 1.2 100 1901.6 1.2 100
"RcppAlgos::comboGeneral" 1.2 100 1901.6 0.0 0
Rprof("arrangements.out", memory.profiling = TRUE)
t3 <- arrangements::combinations(10^3, 3, testVector7)
Rprof(NULL)
summaryRprof("arrangements.out", memory = "both")$by.total
total.time total.pct mem.total self.time self.pct
".Call" 2.08 99.05 1901.6 2.08 99.05
_
RcppAlgos
&arrangements
を使用すると、_mem.total
_は_1900 Mb
_のすぐ上に登録されます。
そして、これがgtools
、utils
、およびcombinat
を比較する小さなベクトルのメモリプロファイルです。
_testVector7Prime <- testVector7[1:300]
Rprof("combinat.out", memory.profiling = TRUE)
t3 <- combinat::combn(testVector7Prime, 3)
Rprof(NULL)
summaryRprof("combinat.out", memory = "both")$by.total
total.time total.pct mem.total self.time self.pct
"combinat::combn" 3.98 100.00 1226.9 3.72 93.47
Rprof("utils.out", memory.profiling = TRUE)
t4 <- utils::combn(testVector7Prime, 3)
Rprof(NULL)
summaryRprof("utils.out", memory = "both")$by.total
total.time total.pct mem.total self.time self.pct
"utils::combn" 2.52 100.00 1952.7 2.50 99.21
Rprof("gtools.out", memory.profiling = TRUE)
t5 <- gtools::combinations(300, 3, testVector7Prime)
Rprof(NULL)
summaryRprof("gtools.out", memory = "both")$by.total
total.time total.pct mem.total self.time self.pct
"rbind" 4.94 95.00 6741.6 4.40 84.62
_
興味深いことに、_utils::combn
_と_combinat::combn
_は異なるメモリ量を使用し、実行に異なる時間を要します。これは、より小さなベクトルでは成り立ちません。
_microbenchmark(combinat::combn(2:13, 6), utils::combn(2:13, 6))
Unit: microseconds
expr min lq mean median uq max neval
combinat::combn(2:13, 6) 527.378 567.946 629.1268 577.163 604.3270 1816.744 100
utils::combn(2:13, 6) 663.150 712.872 750.8008 725.716 771.1345 1205.697 100
_
また、gtools
を使用すると、使用される合計メモリはutils
の3倍強になります。これらの3つのパッケージでは、実行するたびに異なる結果が得られたことに注意してください(たとえば、_combinat::combn
_の場合、9000 Mbを取得してから13000 Mbを取得することがあります)。
それでも、どれもRcppAlgos
[〜#〜]または[〜#〜]arrangements
に一致することはできません。上記の例で実行した場合、どちらも51 Mbのみを使用します。
ベンチマークスクリプト:---(https://Gist.github.com/randy3k/bd5730a6d70101c7471f4ae6f453862e ( https://github.com/tidyverse/reprex によってレンダリング)
*:A Comb through Combinatorics]へのオマージュMiklósBóna作