【问题标题】:R Populate column based on matching rows values in two different data framesR根据两个不同数据框中的匹配行值填充列
【发布时间】:2022-01-13 13:57:08
【问题描述】:

我有两个不同的数据框“df1”和“df2”,有六个匹配的列名。我想扫描 df2 中与 df1 完全匹配的行,如果它们确实在 df1 的“检测”列中输入 1,如果没有在该列中输入 0。目前 df1 中的所有“检测”值都是 0,但我希望在两个数据帧之间完全匹配时将它们更改为 1。它看起来像这样:

df1

site ddate ssegment spp vtype tperiod detect
BMA 6/1/2021 1 AMRO Song 1 0
BMC 6/15/2021 1 WISN Drum 1 0
BMA 6/15/2021 1 NOFL Song 2 0
BMC 6/29/2021 2 AMRO Call 1 0
BMA 6/29/2021 2 WISN Call 2 0

df2

site ddate ssegment spp vtype tperiod
BMA 6/1/2021 1 AMRO Call 1
BMC 6/15/2021 1 WISN Drum 1
BMA 6/15/2021 1 NOFL Song 2
BMC 6/29/2021 2 AMRO Drum 1
BMA 6/29/2021 2 WISN Call 2

扫描这些后,df1 现在看起来像:

df1

site ddate ssegment spp vtype tperiod detect
BMA 6/1/2021 1 AMRO Song 1 0
BMC 6/15/2021 1 WISN Drum 1 1
BMA 6/15/2021 1 NOFL Song 2 1
BMC 6/29/2021 2 AMRO Call 1 0
BMA 6/29/2021 2 WISN Call 2 1

我在想 R 基函数“合并”可能有用,但我不太明白。感谢您的帮助!

【问题讨论】:

    标签: r merge


    【解决方案1】:

    仅从df2 中的detect 列开始,然后合并:

    df1$detect = NULL
    df2$detect = 1
    result = merge(df1, unique(df2), all.x = TRUE)
    

    这会将detect 列在完全匹配时创建为 1,在没有完全匹配时创建为 NAs。如果需要,可以将NAs 更改为 0。

    同样的方法也适用于dplyr

    library(dplyr)
    df1 %>% 
      select(-detect) %>%
      left_join(
        df2 %>% mutate(detect = 1) %>% unique)
      )
    

    【讨论】:

    • 这个答案似乎有效,但数学并没有加起来。本质上,我的实际 df1 有 38880 行,而 df2 有 5854 行。 “结果”应该有 38880 行(与 df1 相同),因为我想要的只是将 df1 的 5854 行与 df2 完全匹配的“检测”列数据更改为 1。我知道 df2 中的每一行在 df1 中都有一个匹配的行。您的结果在“结果”中留下了 42702 行。任何想法可能会发生什么?
    • 这意味着您有一些包含多个匹配项的行。首先对df2 进行重复数据删除应该可以解决这个问题。我将编辑以在merge() 中使用unique(df2)
    • 这似乎是正确的。感谢您为此付出的努力!
    【解决方案2】:

    anti_joinsemi_join 用于两个表的过滤连接:

    library(tidyverse)
    
    df1 <- tribble(
      ~site,      ~ddate, ~ssegment,   ~spp, ~vtype, ~tperiod, ~detect,
      "BMA",  "6/1/2021",        1L, "AMRO", "Song",       1L,      0L,
      "BMC", "6/15/2021",        1L, "WISN", "Drum",       1L,      0L,
      "BMA", "6/15/2021",        1L, "NOFL", "Song",       2L,      0L,
      "BMC", "6/29/2021",        2L, "AMRO", "Call",       1L,      0L,
      "BMA", "6/29/2021",        2L, "WISN", "Call",       2L,      0L
      )
    
    df2 <- tibble::tribble(
    ~site,      ~ddate, ~ssegment,   ~spp, ~vtype, ~tperiod,
    "BMA",  "6/1/2021",        1L, "AMRO", "Call",       1L,
    "BMC", "6/15/2021",        1L, "WISN", "Drum",       1L,
    "BMA", "6/15/2021",        1L, "NOFL", "Song",       2L,
    "BMC", "6/29/2021",        2L, "AMRO", "Drum",       1L,
    "BMA", "6/29/2021",        2L, "WISN", "Call",       2L
    )
    
    
    bind_rows(
      df1 %>% select(-detect) %>% anti_join(df2) %>% mutate(detect = 0),
      df1 %>% select(-detect) %>% semi_join(df2) %>% mutate(detect = 1)
    )
    #> Joining, by = c("site", "ddate", "ssegment", "spp", "vtype", "tperiod")
    #> Joining, by = c("site", "ddate", "ssegment", "spp", "vtype", "tperiod")
    #> # A tibble: 5 x 7
    #>   site  ddate     ssegment spp   vtype tperiod detect
    #>   <chr> <chr>        <int> <chr> <chr>   <int>  <dbl>
    #> 1 BMA   6/1/2021         1 AMRO  Song        1      0
    #> 2 BMC   6/29/2021        2 AMRO  Call        1      0
    #> 3 BMC   6/15/2021        1 WISN  Drum        1      1
    #> 4 BMA   6/15/2021        1 NOFL  Song        2      1
    #> 5 BMA   6/29/2021        2 WISN  Call        2      1
    

    reprex package (v2.0.1) 于 2021-12-08 创建

    【讨论】:

    • 这个答案似乎工作得很好,就像下面的那个。我对 R 的了解不够多,无法推荐其中一个。感谢您的宝贵时间!
    【解决方案3】:

    请使用data.table 库找到一种可能且非常简单的解决方案

    Reprex

    • 代码
    library(data.table)
    
    setDT(df1)
    setDT(df2)
    
    df1[df2, on = .(site, ddate, ssegment, spp, vtype, tperiod), detect := TRUE][]
    
    • 输出
    
    #>    site     ddate ssegment  spp vtype tperiod detect
    #> 1:  BMA  6/1/2021        1 AMRO  Song       1      0
    #> 2:  BMC 6/15/2021        1 WISN  Drum       1      1
    #> 3:  BMA 6/15/2021        1 NOFL  Song       2      1
    #> 4:  BMC 6/29/2021        2 AMRO  Call       1      0
    #> 5:  BMA 6/29/2021        2 WISN  Call       2      1
    

    reprex package (v2.0.1) 于 2021-12-08 创建

    【讨论】:

    • 您忘记在代码中添加“spp”,所以我在“ssegment”之后添加并运行它,但收到此错误:[.data.frame(df1, df2, on = .( site, ddate, ssegment, : 未使用的参数 (on = .(site, ddate, ssegment, spp, vtype, tperiod))
    • 抱歉这个错误......所以,我在我的代码中添加了缺失的变量,它仍然有效。请告诉我。
    • 我猜你的问题是 df1 和 df2 是数据框。因此,您需要在使用 setDT(df1)setDT(df2) 之前将其转换为 data.table 我将在我的答案中添加它。请告诉我。
    • 此解决方案也适用。感谢您的努力!
    • 感谢您的反馈。我祝你工作顺利。干杯
    猜你喜欢
    • 2019-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-13
    • 1970-01-01
    • 2017-02-10
    • 2020-12-02
    • 1970-01-01
    相关资源
    最近更新 更多