查看一个数据帧行中的所有值是否存在于另一个数据帧中

时间:2017-03-25 15:42:39

标签: r dplyr match

我的数据框如下:

df1    

ColA     ColB     ColC     ColD
  10        A        B        L
  11        N        Q       NA
  12        P        J        L
  43        M        T       NA
  89        O        J        T

df2

ATTR      Att      R1   R2    R3    R4
   1       45       A    B    NA    NA
   2       40       C    D    NA    NA
   3       33       T    J     O    NA
   4       65       L   NA    NA    NA
   5       20       P    L     J    NA
   6       23       Q   NA    NA    NA
   7       38       Q    L    NA    NA

如何将df2与df1匹配,以便如果df2行中的所有值(忽略顺序)显示在df1行中,那么它将填充。因此,检查所有不是每个df2行中的一个值是否与每个df1行匹配。这种情况下的最终结果应该是:

ColA     ColB     ColC     ColD   ATTR      Att      R1   R2    R3    R4
  10        A        B        L      1       45       A    B    NA    NA
  10        A        B        L      4       65       L   NA    NA    NA
  11        N        Q       NA      6       23       Q   NA    NA    NA
  12        P        J        L      4       65       L   NA    NA    NA
  12        P        J        L      5       20       P    L     J    NA    
  89        O        J        T      3       33       T    J     O    NA

由于

1 个答案:

答案 0 :(得分:1)

这是使用基础R的可能解决方案。

在继续之前确保一切都是一个角色,即

df[-1] <- lapply(df[-1], as.character)
df1[-c(1:2)] <- lapply(df1[-c(1:2)], as.character)

首先,我们创建两个列表,其中包含每个数据帧的行元素的向量。然后我们创建一个矩阵,其中l2的元素长度在l1中找到,如果长度为0则表示它们匹配。即,

l1 <- lapply(split(df[-1], seq(nrow(df))), function(i) i[!is.na(i)])
l2 <- lapply(split(df1[-c(1:2)], seq(nrow(df1))), function(i) i[!is.na(i)])

m1 <- sapply(l1, function(i) sapply(l2, function(j) length(setdiff(j, i))))
m1
#  1 2 3 4 5
#1 0 2 2 2 2
#2 2 2 2 2 2
#3 3 3 2 2 0
#4 0 1 0 1 1
#5 2 3 0 3 2
#6 1 0 1 1 1
#7 1 1 1 2 2

然后我们使用该矩阵在原始df中创建几个coloumns。第一列rpt将指示每行的长度为0的次数,并将其用作每行的重复次数。我们还使用它来过滤掉所有0个长度(即与df1不匹配的行)。扩展数据框后,我们创建另一个变量; ATTR(与ATTR中的df1同名),以便将其用于merge。即。

df$rpt <- colSums(m1 == 0)
df <- df[df$rpt != 0,]
df <- df[rep(row.names(df), df$rpt),]
df$ATTR <- which(m1 == 0, arr.ind = TRUE)[,1]
df
#    ColA ColB ColC ColD rpt ATTR
#1     10    A    B    L   2    1
#1.1   10    A    B    L   2    4
#2     11    N    Q <NA>   1    6
#3     12    P    J    L   2    4
#3.1   12    P    J    L   2    5
#5     89    O    J    T   1    3

然后我们merge并订购两个数据框

final_df <- merge(df, df1, by = 'ATTR')

final_df[order(final_df$ColA),]
#  ATTR ColA ColB ColC ColD rpt Att R1   R2   R3   R4
#1    1   10    A    B    L   2  45  A    B <NA> <NA>
#3    4   10    A    B    L   2  65  L <NA> <NA> <NA>
#6    6   11    N    Q <NA>   1  23  Q <NA> <NA> <NA>
#4    4   12    P    J    L   2  65  L <NA> <NA> <NA>
#5    5   12    P    J    L   2  20  P    L    J <NA>
#2    3   89    O    J    T   1  33  T    J    O <NA>

数据

dput(df)
structure(list(ColA = c(10L, 11L, 12L, 43L, 89L), ColB = c("A", 
"N", "P", "M", "O"), ColC = c("B", "Q", "J", "T", "J"), ColD = c("L", 
NA, "L", NA, "T")), .Names = c("ColA", "ColB", "ColC", "ColD"
), row.names = c(NA, -5L), class = "data.frame")

dput(df1)
structure(list(ATTR = 1:7, Att = c(45L, 40L, 33L, 65L, 20L, 23L, 
38L), R1 = c("A", "C", "T", "L", "P", "Q", "Q"), R2 = c("B", 
"D", "J", NA, "L", NA, "L"), R3 = c(NA, NA, "O", NA, "J", NA, 
NA), R4 = c(NA_character_, NA_character_, NA_character_, NA_character_, 
NA_character_, NA_character_, NA_character_)), .Names = c("ATTR", 
"Att", "R1", "R2", "R3", "R4"), row.names = c(NA, -7L), class = "data.frame")