Rのマトリックスよりもデータフレームで「一意」を実行するのはなぜですか?
-
26-10-2019 - |
質問
私は、表記の利便性を除いて、データフレームがマトリックスよりも利点がないと信じ始めています。しかし、私は走るときにこの奇妙さに気づきました unique
マトリックスとデータフレームでは、データフレームでより速く実行されるようです。
a = matrix(sample(2,10^6,replace = TRUE), ncol = 10)
b = as.data.frame(a)
system.time({
u1 = unique(a)
})
user system elapsed
1.840 0.000 1.846
system.time({
u2 = unique(b)
})
user system elapsed
0.380 0.000 0.379
行の数が増えるにつれて、タイミングの結果はさらに大幅に分岐します。したがって、この質問には2つの部分があります。
なぜこれがマトリックスの方が遅いのですか?データフレームに変換する方が速く、実行してください
unique
, 、そして変換します。包むだけではない理由はありますか
unique
のmyUnique
, 、パート#1の変換はどれですか?
注1.マトリックスがアトミックであることを考えると、 unique
マトリックスの方が遅くなるのではなく、より速くする必要があります。固定サイズの連続的なメモリブロックを繰り返すことができることは、一般に、リンクされたリストの個別のブロックを実行するよりも高速でなければなりません(それがデータフレームの実装方法だと思います...)。
注2.のパフォーマンスによって示されているように data.table
, 、 ランニング unique
データフレームまたはマトリックスは比較的悪い考えです - マシュー・ダウルによる答えと相対的なタイミングのコメントを参照してください。私は多くのオブジェクトをデータテーブルに移行しましたが、このパフォーマンスはそうするもう1つの理由です。したがって、ユーザーはデータテーブルを採用するのに適切に提供されるべきですが、教育的 /コミュニティの理由から どうして マトリックスオブジェクトでこれには時間がかかりますか。以下のアドレスの回答 どこ 時間はありますか、そして 他には より良いパフォーマンスを得ることができますか(つまり、データテーブル)。の答え どうして 近くにあります - コードは経由で見つけることができます unique.data.frame
と unique.matrix
. 。 :)それが何をしているのか、そしてなぜすべてが欠けているのかについての英語の説明。
解決
この実装では、
unique.matrix
と同じですunique.array
> identical(unique.array, unique.matrix)
[1] TRUE
unique.array
余分な寸法を「崩壊」するために追加の処理が必要な多次元配列を処理する必要があります(それらの追加の呼び出しpaste()
)2次元の場合は必要ありません。コードの重要なセクションは次のとおりです。collapse <- (ndim > 1L) && (prod(dx[-MARGIN]) > 1L)
temp <- if (collapse) apply(x, MARGIN, function(x) paste(x, collapse = "\r"))
unique.data.frame
2Dケースに最適化されています。unique.matrix
ではありません。あなたが提案するように、それは現在の実装ではないかもしれません。
すべての場合において、複数の次元がある場合、一意性と比較される文字列表現であることに注意してください。浮動小数点数の場合、これは15桁の数字を意味しますので
NROW(unique(a <- matrix(rep(c(1, 1+4e-15), 2), nrow = 2)))
は 1
その間
NROW(unique(a <- matrix(rep(c(1, 1+5e-15), 2), nrow = 2)))
と
NROW(unique(a <- matrix(rep(c(1, 1+4e-15), 1), nrow = 2)))
両方とも 2
. 。あなたは 承知しました unique
あなたが欲しいものは何ですか?
他のヒント
確かではありませんが、そうだと思います
matrix
1つの隣接するベクトルであり、Rは最初に列ベクトルにコピーします(data.frame
) なぜならpaste
ベクトルのリストが必要です。両方が使用されるため、両方とも遅いことに注意してくださいpaste
.おそらく
unique.data.table
すでに何倍も速いです。 r-forgeリポジトリからダウンロードしてv1.6.7にアップグレードしてください。unique
あなたは育てました この質問.data.table
使用しませんpaste
やるunique
.
a = matrix(sample(2,10^6,replace = TRUE), ncol = 10) b = as.data.frame(a) system.time(u1<-unique(a)) user system elapsed 2.98 0.00 2.99 system.time(u2<-unique(b)) user system elapsed 0.99 0.00 0.99 c = as.data.table(b) system.time(u3<-unique(c)) user system elapsed 0.03 0.02 0.05 # 60 times faster than u1, 20 times faster than u2 identical(as.data.table(u2),u3) [1] TRUE
自分の質問、特にパート1に答えようとする際に、結果を調べることで時間がどこに費やされているかを見ることができます Rprof
. 。 5mの要素でこれを再び実行しました。
最初の一意の操作(マトリックス用)の結果は次のとおりです。
> summaryRprof("u1.txt")
$by.self
self.time self.pct total.time total.pct
"paste" 5.70 52.58 5.96 54.98
"apply" 2.70 24.91 10.68 98.52
"FUN" 0.86 7.93 6.82 62.92
"lapply" 0.82 7.56 1.00 9.23
"list" 0.30 2.77 0.30 2.77
"!" 0.14 1.29 0.14 1.29
"c" 0.10 0.92 0.10 0.92
"unlist" 0.08 0.74 1.08 9.96
"aperm.default" 0.06 0.55 0.06 0.55
"is.null" 0.06 0.55 0.06 0.55
"duplicated.default" 0.02 0.18 0.02 0.18
$by.total
total.time total.pct self.time self.pct
"unique" 10.84 100.00 0.00 0.00
"unique.matrix" 10.84 100.00 0.00 0.00
"apply" 10.68 98.52 2.70 24.91
"FUN" 6.82 62.92 0.86 7.93
"paste" 5.96 54.98 5.70 52.58
"unlist" 1.08 9.96 0.08 0.74
"lapply" 1.00 9.23 0.82 7.56
"list" 0.30 2.77 0.30 2.77
"!" 0.14 1.29 0.14 1.29
"do.call" 0.14 1.29 0.00 0.00
"c" 0.10 0.92 0.10 0.92
"aperm.default" 0.06 0.55 0.06 0.55
"is.null" 0.06 0.55 0.06 0.55
"aperm" 0.06 0.55 0.00 0.00
"duplicated.default" 0.02 0.18 0.02 0.18
$sample.interval
[1] 0.02
$sampling.time
[1] 10.84
データフレームの場合:
> summaryRprof("u2.txt")
$by.self
self.time self.pct total.time total.pct
"paste" 1.72 94.51 1.72 94.51
"[.data.frame" 0.06 3.30 1.82 100.00
"duplicated.default" 0.04 2.20 0.04 2.20
$by.total
total.time total.pct self.time self.pct
"[.data.frame" 1.82 100.00 0.06 3.30
"[" 1.82 100.00 0.00 0.00
"unique" 1.82 100.00 0.00 0.00
"unique.data.frame" 1.82 100.00 0.00 0.00
"duplicated" 1.76 96.70 0.00 0.00
"duplicated.data.frame" 1.76 96.70 0.00 0.00
"paste" 1.72 94.51 1.72 94.51
"do.call" 1.72 94.51 0.00 0.00
"duplicated.default" 0.04 2.20 0.04 2.20
$sample.interval
[1] 0.02
$sampling.time
[1] 1.82
私たちが気づくのは、マトリックスバージョンが多くの時間を費やしていることです apply
, paste
, 、 と lapply
. 。対照的に、データフレームバージョンは単純に実行されます duplicated.data.frame
そして、ほとんどの時間は費やされています paste
, 、おそらく結果の集計です。
これは説明していますが どこ 時が来ました、それは説明しません どうして これらには、実装が異なることも、あるオブジェクトタイプから別のオブジェクトタイプに単純に変更する効果もありません。