R数据表 - 仅保留具有重复ID的行(最有效的解决方案)

6

我想使用data.table创建一个函数,只保留ID列(作为字符串向量存储)重复的行。请注意,在存在多个ID列的情况下,我只想保留ID列组合重复的行。

library(data.table)

dt <- data.table(x = c(1:5,5), y = rep(c(1,3,5), each = 2), z = rep(1:3, 2))

get_duplicate_id_rows1 <- function(dt_in, id_str) {
  dt_in[, if(.N > 1) .SD, by = id_str]
}

get_duplicate_id_rows1(dt, c("x", "y"))
#>    x y z
#> 1: 5 5 2
#> 2: 5 5 3

get_duplicate_id_rows1(dt[, .(x,y)], c("x", "y"))
#> Empty data.table (0 rows and 2 cols): x,y

与上文相同,当数据表只有一个非ID列时,我的第一次尝试成功。但是,当所有列都是ID列时,数据表就没有行了。我认为这是因为,根据?data.table的说明,.SD包含原始数据表的所有变量,除了分组行。因此,.SD没有任何列,这似乎导致了我的问题。
get_duplicate_id_rows2 <- function(dt_in, id_str) {
  dt_in[, if(.N > 1) .SD, by = id_str, .SDcols = names(dt_in)]
}

get_duplicate_id_rows2(dt, c("x", "y"))
#>    x y x y z
#> 1: 5 5 5 5 2
#> 2: 5 5 5 5 3

get_duplicate_id_rows2(dt[, .(x,y)], c("x", "y"))
#>    x y x y
#> 1: 5 5 5 5
#> 2: 5 5 5 5

我尝试使用.SDcols来解决第一次尝试中的问题。这确实解决了数据表中所有列都是ID列的问题。但是,在id_str中的列名重复了。

我认为这是因为一组列名来自by参数,另一组列名来自.SDcols。不过我不能确定,因为在我的第一次尝试中,结果数据表行数为零,而不是列数。

因此,我希望理解这里发生了什么以及如何最有效地解决我的问题-特别是对于大型数据集,这就是我从tidyverse转向data.table的原因。

reprex包(v0.3.0)于2020-04-09创建

2个回答

3
我们可以使用.I来获取频率计数大于1的组的索引,提取列并对数据表进行子集处理。
dt[dt[, .I[.N >1], .(x, y)]$V1]

注意:它应该比.SD更快。


3

以下是另一个选项:

dt[dt[rowid(x, y) > 1], on=.(x, y), .SD]

在示例中,你对于返回0行的解释是正确的。由于分组列用于分组,因此它对于每个组都是相同的,并且可以通过.BY访问,因此.SD不需要具有这些列以防止重复。
默认情况下,在使用by时,这些列也会作为输出中最左侧的列返回,因此在get_duplicate_id_rows2中,您将看到x、y,然后是来自.SDcols指定的.SD中的列。
最后,关于效率,您可以使用microbenchmark对此处发布的各种选项进行计时,并使用实际数据集共享您的结果。

  1. 我实际上从未使用过 id_str = c("x", "y", "z")
  2. 有道理!
  3. 当然!更多地想知道为什么某些选项比其他选项更有效率。如果没有表达清楚,敬请谅解。
- user3646834
哦,我误解了“然而,当所有列都是ID列时,数据表就没有行了。”。你的意思是什么? - chinsoon12
抱歉我没有表达清楚!请查看get_duplicate_id_rows1(dt[, .(x,y)], c("x", "y"))的输出。另外,你的答案产生了第三列i.z,并且并非所有行的值都等于z - user3646834
1
添加了一个.SD后,你对为什么它返回0行的理解是正确的,即依据?data.table.SD包括原始数据表的所有变量,除了分组行。因此,.SD没有任何列,这似乎导致了我的问题。 - chinsoon12

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