我有两个数据帧:
> df1:
a b
1 1 2
2 2 3
3 2 4
4 3 4
5 4 4
> df2:
a b
1 1 1
2 1 2
3 2 3
4 3 4
5 5 5
然后合并df1和df2以获取df3,请注意合并by=c("a","b")
df3<-merge(df1,df2)
> df3
a b
1 1 2
2 2 3
3 3 4
我想得到df1中选择的行索引,并在df1中添加一个列调用“label”。
> df1:
a b label
1 1 2 TRUE
2 2 3 TRUE
3 2 4 FALSE
4 3 4 TRUE
5 4 4 FALSE
我试过了:
df1$label<-apply(df1,1,function (x) ifelse(nrow(merge(x,df3))>0,TRUE,FALSE))
得到了错误的结果,因为我的df1非常大,所以速度很慢。 有什么简单的方法吗?像载体中的is.element?谢谢。
答案 0 :(得分:1)
在a
和b
上合并,在SQL中执行等效的LEFT OUTER JOIN
,然后为值FALSE
分配不匹配的行:
df1 <- data.frame(a=c(1,2,2,3,4), b=c(2,3,4,4,4))
df2 <- data.frame(a=c(1,1,3,5), b=c(1,2,4,5))
df2$label <- TRUE # df1 matches to df2 is TRUE
df3 <- merge(df1, df2, by=c("a", "b"), all.x=TRUE) # merge on a AND b
df3$label[is.na(df3$label)] <- FALSE # non-match is FALSE
输出:
> df3
a b label
1 1 2 TRUE
2 2 3 TRUE
3 2 4 FALSE
4 3 4 TRUE
5 4 4 FALSE
答案 1 :(得分:1)
这是使用data.table
的另一种方式:
require(data.table)
setkey(setDT(df1), a) ## (1)
idx = df1[df2, which=TRUE, nomatch=0L] ## (2)
df1[, label := FALSE][idx, label := TRUE] ## (3)
df1
# a b label
# 1: 1 2 TRUE
# 2: 2 3 FALSE
# 3: 3 4 TRUE
# 4: 4 5 FALSE
setDT
通过引用将data.frame转换为data.table。在data.table上,我们在setkey
列上a
- 它基本上按列a
和标记重新排序data.table df1 该列已排序。这是在步骤2中完成加入的先决条件。
我们会在x[i]
和x=df1
之间执行i=df2
表单的联接。 x
必须是键控的 data.table,i
可以是list,data.frame或data.table。联接在密钥列a
上执行。对于 df2 的列a
的每一行,我们找到匹配的行,并使用参数which=TRUE
返回它们,如果不匹配,我们返回一个使用nomatch=0L
为该行的“0”。
在此步骤中,我们获得idx = 1, 3, 0
。因为“1”和“3”匹配第一行和第三行,“5”不匹配。
我们将整个label
列设置为FALSE
,并仅将idx
的行更新为TRUE
(这些是匹配的行)。这是通过使用:=
运算符再次引用(速度和内存效率)来完成的。
查看HTML vignettes了解详情。
答案 2 :(得分:0)
如果数据集很大,您也可以尝试data.table
library(data.table)
setkey(setDT(df2),a)[df1][,c('label','b') :=
list(!is.na(b), i.b)][,i.b:= NULL][]
# a b label
#1: 1 2 TRUE
#2: 2 3 FALSE
#3: 3 4 TRUE
#4: 4 5 FALSE