【问题标题】:Seeing if all values in one dataframe row exist in another dataframe查看一个数据帧行中的所有值是否存在于另一个数据帧中
【发布时间】:2017-08-18 12:09:31
【问题描述】:

我有一个如下的数据框:

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

谢谢

【问题讨论】:

    标签: r dplyr match


    【解决方案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 中创建几个列。第一列rpt 将指示每行长度为0 的次数,并将其用作每行的重复次数。我们还使用它来过滤掉所有 0 长度(即与 df1 不匹配的行)。扩展数据框后,我们创建另一个变量; ATTR(与df1 中的ATTR 同名)以便将其用于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")
    

    【讨论】:

    • 这看起来可行!不能感谢你。一种非常直观的方法。谢谢@Sotos
    猜你喜欢
    • 1970-01-01
    • 2022-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 2017-11-18
    相关资源
    最近更新 更多