如何使用与第二个数据框中的行匹配的两个变量标记行? [R

时间:2014-07-17 16:47:54

标签: r

我有两个大数据集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和其他论坛而没有运气。感谢。

5 个答案:

答案 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