data.table 具有两个字符串列的集合元素,提取唯一的行,每行未排序

Posted

技术标签:

【中文标题】data.table 具有两个字符串列的集合元素,提取唯一的行,每行未排序【英文标题】:data.table with two string columns of set elements, extract unique rows with each row unsorted 【发布时间】:2014-09-28 12:55:16 【问题描述】:

假设我有一个这样的 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 删除重复项。如果我有数百万行,排序过程会很慢。那么有没有一种简单的方法可以在不排序的情况下删除重复项?

【问题讨论】:

你只有两列吗? @eddi 目前是。这有关系吗? 多个字符串 data.table 列不是表示集合成员资格的好方法,我会使用可以处理 32 个元素的位域。在此操作之后,您最终要对这些行做什么? 【参考方案1】:

对于只有两列,您可以使用以下技巧:

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

【讨论】:

【参考方案2】:

从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)。

【讨论】:

【参考方案3】:

这是删除重复行的简单方法。

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

【讨论】:

以上是关于data.table 具有两个字符串列的集合元素,提取唯一的行,每行未排序的主要内容,如果未能解决你的问题,请参考以下文章

将字符串列拆分为几个虚拟变量

使用pyspark将两个字符串列值连接到整数数组

过滤具有特定字符的字符串列[关闭]

如何在条件与数字之间使用 Oracle 中的字符串列

将具有日期和纪元格式值的字符串列转换为 postgresql/Tableau prep 中的日期列

将具有 AM/PM 的字符串列转换为 Impala 中的时间戳