[英]Find repeating groups in r data.table
我需要在 r 数据表中识别和删除重复的记录组(但我认为问题在任何编程语言中都是相同的),结构如下:
组由 var1 和 var2 中的值标识,如果它们具有相同的大小并且在 var2 和 var3 中包含相同的值,则它们是重复的(var3 中的值是由 var1 和 var2 标识的更大组的共同点)。
因此,在示例中,2 个红色组是重复的,但对 (red,blue) 和对 (red,brown) 不是。
我的解决方案是将表格转换为宽格式
然后执行unique(dt[,var1:=NULL])
并转回长格式(此时我不再需要 var1 )。
问题是我的真实表格有 165,391,868 条记录,这不是一次性任务,而是每周一次的任务,表格大小相似,时间有限。
我尝试将表拆分成块,附加它们,然后进行重复数据删除,但第一个转置现在已经运行了 2 小时以上!
任何替代和最快的解决方案? 非常感谢!
创建示例表的代码:
dt <- data.table(
var1=c(
"value1_1",
"value1_1",
"value1_1",
"value1_2",
"value1_2",
"value1_2",
"value1_2",
"value1_3",
"value1_3",
"value1_3",
"value1_4",
"value1_4",
"value1_4",
"value1_5",
"value1_5",
"value1_5",
"value1_5"),
var2=c(
"value2_1",
"value2_1",
"value2_1",
"value2_1",
"value2_1",
"value2_1",
"value2_1",
"value2_1",
"value2_1",
"value2_1",
"value2_1",
"value2_1",
"value2_1",
"value2_1",
"value2_1",
"value2_1",
"value2_1"),
var1=c(
"value3_1",
"value3_2",
"value3_3",
"value3_2",
"value3_4",
"value3_5",
"value3_6",
"value3_1",
"value3_2",
"value3_3",
"value3_1",
"value3_2",
"value3_4",
"value3_1",
"value3_2",
"value3_3",
"value3_5"))
这里有 2 个其他选项:
1) 将var3
折叠成单个值以进行连接
lu <- dt[, paste(var3, collapse=""), .(var1, var2)]
samegrp <- lu[lu, on=.(V1)][
var1!=i.var1 & var2==i.var2,
.(var1=c(var11, var12), g=.GRP),
.(var11=pmin(var1, i.var1), var12=pmax(var1, i.var1), var2)]
dt[samegrp, on=.(var1, var2), g := g]
output:
var1 var2 var3 g
1: value1_1 value2_1 value3_1 1
2: value1_1 value2_1 value3_2 1
3: value1_1 value2_1 value3_3 1
4: value1_2 value2_1 value3_2 NA
5: value1_2 value2_1 value3_4 NA
6: value1_2 value2_1 value3_5 NA
7: value1_2 value2_1 value3_6 NA
8: value1_3 value2_1 value3_1 1
9: value1_3 value2_1 value3_2 1
10: value1_3 value2_1 value3_3 1
11: value1_4 value2_1 value3_1 NA
12: value1_4 value2_1 value3_2 NA
13: value1_4 value2_1 value3_4 NA
14: value1_5 value2_1 value3_1 NA
15: value1_5 value2_1 value3_2 NA
16: value1_5 value2_1 value3_3 NA
17: value1_5 value2_1 value3_5 NA
2)匹配计数:
setkey(dt, var1, var2, var3)
count <- dt[, .N, .(var1, var2)]
matches <- dt[dt, on=.(var2, var3), allow.cartesian=TRUE, nomatch=0L][
var1!=i.var1,
.(N=.N / 2, g=.GRP),
.(var11=pmin(i.var1, var1), var12=pmax(i.var1, var1), var2)]
matches[count, on=.(var11=var1, var2, N), nomatch=0L][
count, on=.(var12=var1, var2, N), nomatch=0L]
output:
var11 var12 var2 N g
1: value1_1 value1_3 value2_1 3 1
第二种方法更密集 memory,因此可能会更慢。 但实际性能确实取决于实际数据集的特性。 例如,列的数据类型、 var1
和var2
的唯一对数、 var3
的唯一值的数量等。
我想我有一个解决方案,但如果它不起作用,请告诉我,我会再次破解。
我刚刚通过将 var2 添加到 id 列来响应您的评论进行编辑
首先为基于 var1 和 var2 的组创建一个列
dt[,group:=paste0(var1, var2)]
然后根据 var3 和大小创建一个 id
dt[,id:=paste0(paste(sort(var3), collapse=""), var2, .N), by=group]
然后你 label 每个组都有一个数字,基于它是第一次,第二次,第三次等你看到一个组的 id
dt[,groupN:=as.numeric(factor(group)), by=id]
然后仅在您第一次看到每个组时保留
dt[groupN==1]
这行得通,但我不知道它的效率(老实说,它可能更慢,但它是一种不同的方法)。 我已经为另一个项目构建了多功能滤波器 function,我想到在这里使用它。 multifilter 根据您提供给它的任何列中找到的变量的唯一组合将 dataframe 拆分为数据框列表。 然后我们检查重复的 var 3 cols 并删除它们。 最后数据集被反弹。
multifilter <- function(data,filterorder){
newdata <- list(data)
for(i in rev(filterorder)){
newdata <- unlist(lapply(sort(unique(data[,i])), function(x) lapply(newdata, function(y) y[y[,i]==x,])),recursive=F)
}
return(newdata[sapply(newdata,nrow)>=1])
}
filtereddt <- multifilter(dt,c("var1","var2"))
filtereddt <- filtereddt[-duplicated(lapply(filtereddt, function(x) x[,3]))]
filtereddt <- do.call(rbind, filtereddt)[,-1]
output:
> filtereddt
var2 var3
4 value2_1 value3_2
5 value2_1 value3_4
6 value2_1 value3_5
7 value2_1 value3_6
8 value2_1 value3_1
9 value2_1 value3_2
10 value2_1 value3_3
11 value2_2 value3_1
12 value2_2 value3_2
13 value2_2 value3_4
14 value2_1 value3_1
15 value2_1 value3_2
16 value2_1 value3_3
17 value2_1 value3_5
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.