假设我有一个像这样的data.table:
表:
V1 V2
A B
C D
C A
B A
D C
我希望每一行都被视为一组,这意味着B A和A B是相同的。所以在这个过程之后,我想得到:
V1 V2
A B
C D
C A
为了做到这一点,我必须首先逐行对表进行排序,然后使用unique
删除重复项。如果我有数百万行,排序过程非常慢。那么有没有一种简单的方法来删除重复项而不进行排序?
答案 0 :(得分:15)
对于两列,您可以使用以下技巧:
dt = data.table(a = letters[1:5], b = letters[5:1])
# a b
#1: a e
#2: b d
#3: c c
#4: d b
#5: e a
dt[dt[, .I[1], by = list(pmin(a, b), pmax(a, b))]$V1]
# a b
#1: a e
#2: b d
#3: c c
答案 1 :(得分:3)
从a dupe借入(可能是不现实的)数据:
library(data.table)
size <- 118000000
key1 <- sample( LETTERS, size, replace=TRUE, prob=runif(length(LETTERS), 0.0, 5.0) )
key2 <- sample( LETTERS, size, replace=TRUE, prob=runif(length(LETTERS), 0.0, 5.0) )
val <- runif(size, 0.0, 5.0)
dt <- data.table(key1, key2, val, stringsAsFactors=FALSE)
如果您的数据如下所示,这是一种快速的方法:
# eddi's answer
system.time(res1 <- dt[dt[, .I[1], by=.(pmin(key1, key2), pmax(key1, key2))]$V1])
# user system elapsed
# 101.79 3.01 107.98
# optimized for this data
system.time({
dt2 <- unique(dt, by=c("key1", "key2"))[key1 > key2, c("key1", "key2") := .(key2, key1)]
res2 <- unique(dt2, by=c("key1", "key2"))
})
# user system elapsed
# 8.50 1.16 4.93
fsetequal(copy(res1)[key1 > key2, c("key1", "key2") := .(key2, key1)], res2)
# [1] TRUE
如果这样的数据与协方差有关,那么似乎不太可能,因为您最多应该有一个重复项(即A-B和B-A)。
答案 2 :(得分:-1)
以下是删除重复行的简单方法。
delRows = NULL # the rows to be removed
for(i in 1:nrow(tab)){
j = which(tab$V1 == tab$V2[i] & tab$V2 == tab$V1[i])
j = j [j > i]
if (length(j) > 0){
delRows = c(delRows, j)
}
}
tab = tab[-delRows,]
结果是, 前,
> tab
V1 V2
1 A B
2 C D
3 C A
4 B A
5 D C
后,
> tab
V1 V2
1 A B
2 C D
3 C A