値のリストがあるとします
x <- list(a=c(1,2,3), b = c(2,3,4), c=c(4,5,6))
すべてのリスト要素を組み合わせて一意の値を見つけたいです。これまでのところ、次のコードはトリックを行いました
unique(unlist(x))
誰もがより効率的な方法を知っていますか?私はたくさんの価値がある膨大なリストを持っているので、どんな高速化でも感謝します。
Marekによって提案されたこのソリューションは、元のQに対する最良の回答です。他のアプローチと、Marekが最も有用である理由については、以下を参照してください。
_> unique(unlist(x, use.names = FALSE))
[1] 1 2 3 4 5 6
_
より高速な解決策は、最初にx
のコンポーネントでunique()
を計算し、次にそれらの結果で最後のunique()
を実行することです。これは、以下の両方の例のように、リストのコンポーネントに同じ数の一意の値がある場合にのみ機能します。例えば。:
最初にあなたのバージョン、次に私の二重のユニークなアプローチ:
_> unique(unlist(x))
[1] 1 2 3 4 5 6
> unique.default(sapply(x, unique))
[1] 1 2 3 4 5 6
_
matrix
には1つのマージンを固定するunique
メソッドがあるため、_unique.default
_を呼び出す必要があります。行列はベクトルとして扱うことができるため、これは問題ありません。
マレックは、この回答に対するコメントで、unlist
アプローチの遅い速度は、リスト上のnames
に起因する可能性があると指摘しています。 Marekの解決策は、unlist
に_use.names
_引数を使用することです。これを使用すると、上記の二重の固有バージョンよりも高速な解決策が得られます。 Romanの投稿の単純なx
については、
_> unique(unlist(x, use.names = FALSE))
[1] 1 2 3 4 5 6
_
Marekのソリューションは、コンポーネント間で一意の要素の数が異なる場合でも機能します。
次に、3つの方法すべてのタイミングを含むより大きな例を示します。
_## Create a large list (1000 components of length 100 each)
DF <- as.list(data.frame(matrix(sample(1:10, 1000*1000, replace = TRUE),
ncol = 1000)))
_
DF
を使用した2つのアプローチの結果は次のとおりです。
_> ## Do the three approaches give the same result:
> all.equal(unique.default(sapply(DF, unique)), unique(unlist(DF)))
[1] TRUE
> all.equal(unique(unlist(DF, use.names = FALSE)), unique(unlist(DF)))
[1] TRUE
> ## Timing Roman's original:
> system.time(replicate(10, unique(unlist(DF))))
user system elapsed
12.884 0.077 12.966
> ## Timing double unique version:
> system.time(replicate(10, unique.default(sapply(DF, unique))))
user system elapsed
0.648 0.000 0.653
> ## timing of Marek's solution:
> system.time(replicate(10, unique(unlist(DF, use.names = FALSE))))
user system elapsed
0.510 0.000 0.512
_
これは、二重のunique
がunique()
を個々のコンポーネントに適用してからunique()
に固有の値の小さいセットを適用するよりもはるかに速いことを示していますが、この高速化は純粋にリストnames
のDF
が原因です。 unlist
をnames
を使用しないように指定すると、この問題のMarekの解は、二重のunique
よりもわずかに速くなります。マレックのソリューションは適切なツールを適切に使用しており、回避策よりも高速であるため、推奨されるソリューションです。
ダブルunique
アプローチの大きな落とし穴は、ここの2つの例のように、ifのみが機能することです。入力リスト(DF
またはx
)には、同じ数の一意の値があります。そのような場合、sapply
は結果を行列に整理し、_unique.default
_を適用できるようにします。入力リストのコンポーネントの一意の値の数が異なる場合、二重の一意のソリューションは失敗します。