我有一个非常大的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)
答案 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),并且应进行重复数据删除; - )