我知道这可能是一个简单的问题,但我似乎无法做到这一点。
我有两个数据表数据表 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中被拒绝
有人能帮助我吗?
提前谢谢
答案 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}}可以使用dplyr
,data.frame
,data.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)
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),]