2017-01-21 6 views
1

私はかなり大きなdata.table(500 x 2000)を持っています。その列が重複しているかどうか、つまりすべての行に同じ値があるかどうかを調べる必要があります。 data.table構造体内でこれを効率的に行う方法はありますか?data.tableで重複する列を見つける

私は、列の各ペアに対してall(col1 == col2)という単純な2ループアプローチを試みましたが、時間がかかりすぎます。私はdata.frameに変換して上記の方法を使ってみましたが、まだかなり時間がかかります。

私の現在のソリューションは、行列にdata.tableを変換してapply()機能を使用することです。しかし、アプローチは、すべての要素のモードが同じになるように強制的に、と私は思い

similarity.matrix <- apply(m, 2, function(x) colSums(x == m)))/nrow(m) 

むしろそれが起こることはありません。その他の選択肢は何ですか?ここで

はdata.table用のサンプル構造である:

m = matrix(sample(1:10, size=1000000, replace=TRUE), nrow=500, ncol=2000) 
DF = as.data.frame(m) 
DT = as.data.table(m) 
+0

結果に偽陽性を受け入れるかどうかは、重複列を手動でチェックするかどうかです。私は列ごとに1つのハッシュを計算し、同じハッシュ値が可能な重複を示すと想像することができます。 –

+0

なぜ 'duplicated()'を使わないのですか? – Haboryme

+0

チップをありがとう! duplicated()は不思議に作用します。私の厄介なアプローチよりもはるかに高速です。 – Naumz

答えて

5

重複排除されなければなりません@ Haboryme *の場合、duplicatedを使用してこれを実行して、重複したベクトルを見つけることができます。 duplicatedは通常行ごとに機能しますが、重複を見つけるためにと転記できます。 data.table

DF <- DF[ , which(!duplicated(t(DF))) ] 

、あなたは(私はこれがあなたが使用しているdata.tableのバージョンに依存だと思う)with = FALSEを追加する必要があります。

DT <- DT[ , which(!duplicated(t(DT))), with = FALSE ] 

* @ Haboryme、あなたがあなたのコメントを回答にするつもりなら、私はこれを削除します。

+0

さて、結果は重複していない列インデックスで、それはさらに自動処理に完全に適しています! –

+0

ありがとう@Rヨーダ! – rosscova

+0

'duplicated'には配列のMARGIN引数があり、' t'の代わりに使用できることに注意してください。 'duplicated.array(mtcars、MARGIN = 2)'のようなものです。 – lmo

1

私が再現可能な結果のためにmtcarsを使用しています:

library(data.table) 
library(digest) 

# Create data 
data <- as.data.table(mtcars) 
data[, car.name := rownames(mtcars)] 
data[, car.name.dup := car.name]   # create a duplicated row 
data[, car.name.not.dup := car.name]  # create a second duplicated row... 
data[1, car.name.not.dup := "Moon walker"] # ... but change a value so that it is no longer a duplicated column 

dataは現在含まれています

> head(data) 
    mpg cyl disp hp drat wt qsec vs am gear carb   car.name  car.name.dup car.name.not.dup 
1: 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4   Mazda RX4   Mazda RX4  Moon walker 
2: 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4  Mazda RX4 Wag  Mazda RX4 Wag  Mazda RX4 Wag 
3: 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1  Datsun 710  Datsun 710  Datsun 710 
4: 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 Hornet 4 Drive Hornet 4 Drive Hornet 4 Drive 
5: 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 Hornet Sportabout Hornet Sportabout Hornet Sportabout 
6: 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1   Valiant   Valiant   Valiant 

を重複した列を見つける:

 col.name      hash.value i.col.name 
1: car.name.dup 58fed3da6bbae3976b5a0fd97840591d  car.name 
2:  car.name 58fed3da6bbae3976b5a0fd97840591d car.name.dup 

注:中

# create a vector with the checksum for each column (and keep the column names as row names) col.checksums <- sapply(data, function(x) digest(x, "md5"), USE.NAMES = T) # make a data table with one row per column name and hash value dup.cols <- data.table(col.name = names(col.checksums), hash.value = col.checksums) # self join using the hash values and filter out all column name pairs that were joined to themselves dup.cols[dup.cols,, on = "hash.value"][col.name != i.col.name,] 

結果は結果はまだ両方向(COL1 COL2 ==とcol2 == COL1)が含まれており、提案後;-)

+0

答えてくれてありがとう! – Naumz

2

ここでは、各列を最初にハッシュしてからduplicatedを呼び出す別の方法があります。

library(digest) 
dups <- duplicated(sapply(DF, digest)) 
DF <- DF[,which(!dups)] 

データによっては、これがより高速になる可能性があります。

+0

良いアイデアは、今度は 'duplicated'演算が1列につき1つのハッシュで動作し、' digest'で適切なハッシュアルゴリズムを選択すると、ハッシュ性能とハッシュ衝突密度の間のトレードオフが可能になります。高価な転置は必要ありません。 –

+0

@mpjdemダイジェストへのポインタありがとうございます。それは私のケースをスピードアップしませんでしたが、私は後で使用するためにこれを覚えています。 – Naumz

関連する問題