我有两个大数据集df1和df2。 df2是df1的子集。我想用&#34标记df2中存在的df1行;是"以及#34; No"。行不包含任何唯一的变量值。我想匹配多个变量的值。但是,使用%in%运算符得到的结果不正确。我还尝试了一个嵌套的for循环,它循环遍历df1的每一行,并将它与df2的每一行进行比较。它产生正确的结果但是我的数据集大小需要数天才能完成。
请参阅以下示例:
df1 <- data.frame( Col1 = c( "d1", "d2", "d3", "d1"),
Col2 = c( "n1", "n2", "n1", "n2" ))
df2 <- data.frame( Col1 = c( "d1", "d2" ), Col2 = c( "n1", "n2" ))
df1$Res <- "No"
df1.len <- nrow( df1 )
for ( i in 1:df1.len ){
if ( df1$Col1[i] %in% df2$Col1 &
df1$Col2[i] %in% df2$Col2 ){
df1$Res[i] <- "Yes"
}
}
df1
df2
输出:
DF1 Col1 Col2 Res
1 d1 n1是
2 d2 n2是
3 d3 n1否
4 d1 n2是
DF2
Col1 Col2
1 d1 n1
2 d2 n2
如您所见,df1的第4行在df2中不存在,但仍标记为是。任何帮助将不胜感激。过去几天我一直在寻找SO和其他论坛而没有运气。感谢。
答案 0 :(得分:2)
我会做这样的事情:
duplicated(rbind(df2, df1))[-sequence(nrow(df2))] ## Might not be reliable...
# [1] TRUE TRUE FALSE FALSE
或其中之一:
interaction(df1) %in% interaction(df2)
do.call(paste, df1) %in% do.call(paste, df2)
如果需要,您可以轻松地将TRUE
更改为“是”并将FALSE
更改为“否”,但保留逻辑值可能会更有用。
答案 1 :(得分:1)
我的答案与Ananda的非常相似,只是有点不那么时髦,但是如果你是R的新手可能会更有意义,从我猜测你的问题来判断。
df1 <- data.frame( Col1 = c( "d1", "d2", "d3", "d1"),
Col2 = c( "n1", "n2", "n1", "n2" ))
df2 <- data.frame( Col1 = c( "d1", "d2" ), Col2 = c( "n1", "n2" ))
df1$col3 <- paste0(df1$Col1,df1$Col2) # create a composite of the row
df2$col3 <- paste0(df2$Col1,df2$Col2) # repeat
df1$col3 %in% df2$col3
# [1] TRUE TRUE FALSE FALSE
您不需要将col3添加到您正在使用的数据框中,这就是我的方式。
答案 2 :(得分:1)
这是使用dplyr的答案,它比基础R快得多。首先,为每行创建一个唯一的ID,然后根据比较ID的逻辑向量创建一个新变量。
require(dplyr)
df1 <- data.frame( Col1 = c( "d1", "d2", "d3", "d1"),
Col2 = c( "n1", "n2", "n1", "n2" ))
df2 <- data.frame( Col1 = c( "d1", "d2" ), Col2 = c( "n1", "n2" ))
df2 <- mutate(df2, Col3 = paste0(Col1, Col2))
df1 <- mutate(df1,
Col3 = paste0(Col1, Col2),
Res = ifelse(Col3 %in% df2$Col3, "Yes", "No")
)
使用duplicated()
(如在Ananda的回答中)在语法上很简单,但根据您的数据框有多少列,它可能会非常慢。
答案 3 :(得分:1)
这提供了正确的答案,但如果您在df1和df2中的列具有不同的名称,则需要进行调整:
df1 <- data.frame(Col1 = c("d1", "d2", "d3", "d1"),
Col2 = c("n1", "n2", "n1", "n2"))
df1.len <- nrow(df1)
df1 <- cbind(df1, unique=seq(1:df1.len))
df2 <- data.frame(Col1 = c("d1","d2"), Col2 = c("n1","n2"))
df1$Res <- "No"
match <- merge(df1,df2,by=c("Col1","Col2"))
for (i in 1:df1.len){
if (df1$unique[i] %in% match$unique) {
df1$Res[i] <- "Yes"
}
}
答案 4 :(得分:0)
另一个选择是使用split
,例如,
df1 <- data.frame(a=1:10, b=letters[1:10])
df2 <- df1[1:5,]
df1$in.df2 <- split(df1, rownames(df1)) %in% split(df2, rownames(df2))
# a b in.df2
# 1 1 a TRUE
# 2 2 b TRUE
# 3 3 c TRUE
# 4 4 d TRUE
# 5 5 e TRUE
# 6 6 f FALSE
# 7 7 g FALSE
# 8 8 h FALSE
# 9 9 i FALSE