在data.table中查找重复的列

时间:2017-01-21 10:29:29

标签: r data.table

我有一个非常大的data.table(500 x 2000),我需要找出是否有任何列是重复的,即所有行都有相同的值。有没有办法在data.table结构中有效地做到这一点?

我为每对列尝试了一个带有all(col1 == col2)的朴素双循环方法,但这需要太长时间。我也尝试将其转换为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)

3 个答案:

答案 0 :(得分:5)

根据@ Haboryme *的建议,您可以使用duplicated来查找任何重复的向量。 duplicated通常按行方式工作,但您可以使用t()转置它,仅用于查找重复项。

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

使用data.table,您可能需要添加with = FALSE(我认为这取决于您使用的data.table版本。)

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

* @ Haboryme,如果您要将评论转为答案,请执行此操作,我将删除此评论。

答案 1 :(得分:2)

这是一种不同的方法,首先对每列进行哈希,然后调用duplicated

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

根据您的数据,这可能是一种更快捷的方式。

答案 2 :(得分: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

现在找到重复的列:

# 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,]

结果:

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

注意:结果仍包含两个方向(col1 == col2和col2 == col1),并且应进行重复数据删除; - )