在R的data.table中查找重复的分组

3

我需要在R数据表中识别和去重记录组(但我想在任何编程语言中都是相同的问题),结构如下:

input data.table

组是由var1和var2中的值确定的,如果它们具有相同的大小并且在var2和var3中包含相同的值,则它们是重复的(var3中的值是var1和var2识别的更大组所共有的)。
因此,在示例中,2个红色组是重复的,但是红蓝配对和红棕配对不是。
我的解决方案是将表格转置为宽格式。

transposed data.table

然后执行unique(dt[,var1:=NULL]),再将其转换回长格式(此时我不再需要var1)。

问题在于我的真实表格有165,391,868条记录,这不是一次性任务,而是每周都有类似大小的表格,并且时间有限。

我已经尝试将表格分成块,添加它们,然后执行去重,但第一个转置已经运行了两个多小时!

是否有任何替代方案和更快速的解决方法? 非常感谢!

创建示例表格的代码:

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"))

你期望的输出是什么?只保留绿色、蓝色和棕色行吗? - Ronak Shah
我期望看到绿色、蓝色和棕色的行,以及红色的行只出现一次。 - user3645882
但是两个红色分组具有不同的 var1 值。它们怎么算重复? - Ronak Shah
1
如果你仔细阅读问题,他是说基于var3列和大小进行复制。 - Adam Waring
抱歉,为了成为重复项,它们在var2中也需要相同的值。 - user3645882
嗨,每个列的数据类型是什么?您能否分享一些关于这个巨大数据集的统计数据?鉴于其规模,这是一个有趣的问题。 - chinsoon12
3个回答

1

以下是其他两个选项:

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]

输出:

        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]

输出:

      var11    var12     var2 N g
1: value1_1 value1_3 value2_1 3 1

第二种方法更加占用内存,因此速度可能会更慢。但实际性能取决于实际数据集的特征。例如,列的数据类型、变量对var1和var2的唯一值对数、变量var3的唯一值数量等。

0

我认为我有一个解决方案,但如果不行,请告诉我,我会再试一次。

我刚刚根据您的评论进行了编辑,通过将var2添加到id列中。

首先,基于var1和var2创建一个组列。

dt[,group:=paste0(var1, var2)]

然后你根据var3和大小创建一个id。

dt[,id:=paste0(paste(sort(var3), collapse=""), var2, .N), by=group]

然后,您可以根据您是否已经看到具有该ID的组的第一次、第二次、第三次等来为每个组分配一个基于数字的标签。

dt[,groupN:=as.numeric(factor(group)), by=id]

然后只保留每个组中第一次出现的内容

dt[groupN==1]

好的,它正在工作。我现在正在运行它,看看需要多长时间。 - user3645882
崩溃步骤和转置步骤所需时间一样长,所以对我来说并不适用。 - user3645882
是的,这似乎是一个耗时的步骤。我很想看看是否有人有更快的解决方案。 - Adam Waring

0

这个方法可以运行,但我不知道它的效率如何(老实说,它可能会更慢,但是这是一种不同的方法)。我之前为另一个项目构建了多过滤器函数,并想到在这里使用它。多过滤器函数将数据框根据您提供的列中找到的唯一变量组合拆分成数据框列表。然后我们检查重复的第3列变量并将其删除。最后重新绑定数据集。

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]

输出:

> 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

我遇到了一个错误:Error in [.data.table(data, , i) : j (第二个在[...]中的参数) 是单个符号,但列名 'i' 没有被找到。也许你的意图是 DT[, ..i]。这种与 data.frame 的区别是故意的,并在 FAQ 1.1 中解释。我一直在尝试修复它,但无法解决。 - user3645882

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接