代码之家  ›  专栏  ›  技术社区  ›  Denis

基于数据框中的多列查找值

  •  1
  • Denis  · 技术社区  · 6 年前

    我试图找出如何使用多列查找值。只是似乎无法让它正常工作。以下是一个例子:

    df1 <- data.frame(g1 = c("a", "b", "c", "c"), g2 = c(1, 2, 3, 4))
    df2 <- data.frame(g.1 = c("a", "b", "c"), g.2 = c(1, 2, 4), val = c(100, 200, 300))
    

    df1$value <- df2[match(df1$g1, df2$g.1) & match(df1$g2, df2$g.2),]$val
    

      g1 g2 value
    1  a  1   100
    2  b  2   200
    3  c  3    NA
    4  c  4   300
    
    3 回复  |  直到 6 年前
        1
  •  2
  •   G. Grothendieck    6 年前

    尝试使用左连接 merge

    merge(df1, df2, by = 1:2, all.x = TRUE)
    

    给:

      g1 g2 val
    1  a  1 100
    2  b  2 200
    3  c  3  NA
    4  c  4 300
    

    有些备选方案是:

    transform(df1, val = df2$val[match(paste(g1, g2), paste(df2$g.1, df2$g.2))])
    
    library(sqldf)
    sqldf("select df1.*, df2.val 
           from df1 left join df2 on g1 = [g.1] and g2 = [g.2]")
    
    library(dplyr)
    df1 %>% left_join(df2, by = c(g1 = "g.1", g2 = "g.2"))
    
        2
  •  1
  •   akrun    6 年前

    一个加入会更好,而且更具吸引力 data.table ,当我们更新我的参考资料时,它会变得更有效

    library(data.table)
    setDT(df1)[df2, value := val, on = .(g1 = g.1, g2 = g.2)]
    df1
    #    g1 g2 value
    #1:  a  1   100
    #2:  b  2   200
    #3:  c  3    NA
    #4:  c  4   300
    

    具有 match ,一种方法是 paste 将感兴趣的列放在一起,然后创建一个索引来更改值

    p1 <- do.call(paste, df1)
    p2 <- do.call(paste, df2[1:2])
    i1 <- match(p1, p2, nomatch = 0)
    i2 <- match(p2, p1, nomatch = 0)
    df1$value[i2] <- df2$val[i1]
    df1
    #  g1 g2 value
    #1  a  1   100
    #2  b  2   200
    #3  c  3    NA
    #4  c  4   300
    
        3
  •  0
  •   Denis    6 年前

    根据@G.Grothendieck的回答,我发现我做错了什么。我所要做的就是:

    df1$value <- df2[match(paste0(df1$g1,df1$g2), paste0(df2$g.1,df2$g.2)),]$val