如何在R中对数据表行进行子集以获取对其自身唯一的行

时间:2016-04-08 15:06:34

标签: r data.table subset

我知道这可能是一个简单的问题,但我似乎无法做到这一点。

我有两个数据表数据表 old_dt 和数据表 new_dt 。两个数据表都有两个相似的列。我的目标是从new_dt获取不在old_dt中的行。

这是一个例子。 Old_dt

v1 v2
1 a
2 b
3 c
4 d

这是new_dt

v1 v2
3 c
4 d
5 e

我想要的只是获得5行。

使用 setdiff 无效,因为我的实际数据超过300万行。使用像这样的子集

sub.cti <- subset(new_dt, old_dt$v1 != new_dt$v1 & old_dt$v2!= new_dt$v2)

仅导致new_dt本身。

使用

sub.cti <- subset(new_dt, old_dt$v1 != new_dt$v1 & old_dt$v2!= new_dt$v2)

一无所获。

使用

sub.cti <- new_dt[,.(!old_dt$v1, !old_dt$v2)]

在多行FALSE中被拒绝

有人能帮助我吗?

提前谢谢

4 个答案:

答案 0 :(得分:4)

我们可以join(来自@ giraffehere的帖子的数据)

df2[!df1, on = "a"]
#   a  b
#1: 6 14
#2: 7 15

根据'a'列获取'df1'中不在'df2'中的行

df1[!df2, on = "a"]
#   a  b
#1: 4  9
#2: 5 10

在OP的示例中,我们需要加入on两列

new_dt[!old_dt, on = c("v1", "v2")]
#   v1 v2
#1:  5  e

注意:这里我假设'new_dt'和'old_dt'为data.table s。

当然,dplyr是一个很好的方案。为了解决这个问题,可以使用更短的anti_join

library(dplyr)
anti_join(new_dt, old_dt)
#     v1    v2
#   (int) (chr)
#1     5     e

或来自setdiff的{​​{1}}可以使用dplyrdata.framedata.table等。

tbl_df

但问题标记为setdiff(new_dt, old_dt) # v1 v2 #1: 5 e

答案 1 :(得分:1)

编辑:我注意到OP想要两个行而不只是一个匹配。我将保留解决方案的数据初始化部分,因为@akron在上面引用了它。但是,请使用@akrun发布的顶级解决方案。它更像是“data.table方式”。

df1 <- data.table(a = 1:5, b = 6:10)
df2 <- data.table(a = c(1, 2, 3, 6, 7), b = 11:15)
head(df1)


   a  b
1: 1  6
2: 2  7
3: 3  8
4: 4  9
5: 5 10

head(df2)


   a  b
1: 1 11
2: 2 12
3: 3 13
4: 6 14
5: 7 15

答案 2 :(得分:1)

当您处理R中的表格数据时,dplyr会有很多帮助 - 建议您了解有关dplyr的更多信息here

library(dplyr)
library(magrittr) # this is just for shorter code with %<>%

# Create a sequence number that combine v1 & v2
Old_dt %<>%
  mutate(sequence = paste0(v1,v2))
new_dt %<>%
  mutate(sequence = paste0(v1,v2))

# Filter new_dt by sequence not existed in old_dt
result <- new_dt %>%
  filter(!(sequence %in% Old_dt$sequence)) %>%
  select(v1:v2)

  v1 v2
   5  e

答案 3 :(得分:0)

如果a列重复,你可以尝试这个基础R hack:

id.var1 <- paste(df1$a, df1$b,sep="_")
id.var2 <- paste(df2$a, df2$b,sep="_")

dfKeep <- df[!(id.var2 %in% id.var1),]