【问题标题】:Create a dummy variable column that indicates if a record is in a second dataframe?创建一个虚拟变量列,指示记录是否在第二个数据框中?
【发布时间】:2019-09-21 09:41:15
【问题描述】:

我有两个数据框,df1 和 df2,它们采用这样的格式(最后数据输入的可重现代码):

df1
#>             name instrument
#> 1    John Lennon     guitar
#> 2    Mick Jagger     vocals
#> 3    Ringo Starr      drums
#> 4 Keith Richards     guitar

df2
#>              name beatles
#> 1     John Lennon       1
#> 2     Ringo Starr       1
#> 3 George Harrison       1
#> 4  Paul McCartney       1

我想在 df1 中添加一列,指示一条记录是否也在 df2 中(如果不是,则等于 0),所以我想要的输出是:

output
#>             name instrument beatles
#> 1    John Lennon     guitar       1
#> 2    Mick Jagger     vocals       0
#> 3    Ringo Starr      drums       1
#> 4 Keith Richards     guitar       0

我已经尝试过full_join(),但这会拉动 df2 中不在 df1 中的行,这不是我想要的。 (即 George Harrison 和 Paul McCartney 行不应出现在输出中)


library(tidyverse)

df1 %>% 
  full_join(df2) 

#> Joining, by = "name"
#>              name instrument beatles
#> 1     John Lennon     guitar       1
#> 2     Mick Jagger     vocals      NA
#> 3     Ringo Starr      drums       1
#> 4  Keith Richards     guitar      NA
#> 5 George Harrison       <NA>       1
#> 6  Paul McCartney       <NA>       1

下面的可重现代码:

df1 <- data.frame(stringsAsFactors=FALSE,
         name = c("John Lennon", "Mick Jagger", "Ringo Starr", "Keith Richards"),
   instrument = c("guitar", "vocals", "drums", "guitar")
)

df2 <- data.frame(stringsAsFactors=FALSE,
                name = c("John Lennon", "Ringo Starr", "George Harrison",
                         "Paul McCartney"),
          beatles = c(1, 1, 1, 1)
       )

library(tidyverse)

df1 %>% 
  full_join(df2) 

【问题讨论】:

  • 你想要的是left_join,但它会给你NA。我不认为你可以只使用join 函数一步获得0(我很高兴错了)。

标签: r dplyr tidyverse tidyr


【解决方案1】:
df1$beatles <- ifelse(df1$name %in% df2$name, 1, 0)

            name instrument beatles
1    John Lennon     guitar       1
2    Mick Jagger     vocals       0
3    Ringo Starr      drums       1
4 Keith Richards     guitar       0

或者,如果您在 df2 中也有其他乐队,您可以这样做:

df1$beatles <- ifelse(df1$name %in% df2[df2$beatles == 1,]$name, 1, 0)

【讨论】:

    【解决方案2】:

    这个左连接的data.table解决方案是:

    df1[df2, on = "name", nomatch = 0]
    

    【讨论】:

      【解决方案3】:

      左连接然后变异以用 0 替换 NA

      > library(dplyr)
      
      > output <- df1 %>% left_join(df2, "name") %>% mutate(beatles=ifelse(!is.na(beatles),1,0))
      > output
                  name instrument beatles
      1    John Lennon     guitar       1
      2    Mick Jagger     vocals       0
      3    Ringo Starr      drums       1
      4 Keith Richards     guitar       0
      
      

      【讨论】:

        【解决方案4】:

        另一种解决方案:

        library(magrittr)
        
        df1 <- data.frame(stringsAsFactors = FALSE,
                          name = c("John Lennon", "Mick Jagger", "Ringo Starr", "Keith Richards"),
                          instrument = c("guitar", "vocals", "drums", "guitar"))
        
        df2 <- data.frame(stringsAsFactors = FALSE,
                          name = c("John Lennon", "Ringo Starr", "George Harrison",
                                   "Paul McCartney"),
                          beatles = c(1, 1, 1, 1))
        
        df1 %>%
          dplyr::left_join(y = df2,
                           by = "name") %>%
          tidyr::replace_na(replace = list(beatles = 0))
        #>             name instrument beatles
        #> 1    John Lennon     guitar       1
        #> 2    Mick Jagger     vocals       0
        #> 3    Ringo Starr      drums       1
        #> 4 Keith Richards     guitar       0
        

        【讨论】:

          【解决方案5】:

          我们也可以match两个dataframe的name,将nomatch参数指定为0。如果值大于0则赋值为1。前面的+参数将逻辑值转换为整数。

          df1$beatles <- +(match(df1$name, df2$name, nomatch = 0) > 0)
          df1
          
          #            name instrument beatles
          #1    John Lennon     guitar       1
          #2    Mick Jagger     vocals       0
          #3    Ringo Starr      drums       1
          #4 Keith Richards     guitar       0
          

          【讨论】:

            【解决方案6】:

            我们可以使用 {powerjoin} 并使用fill 参数将不匹配的值填充为0

            library(powerjoin)
            power_left_join(df1, df2, beatles , by="name", fill = 0)
            #>             name instrument beatles
            #> 1    John Lennon     guitar       1
            #> 2    Mick Jagger     vocals       0
            #> 3    Ringo Starr      drums       1
            #> 4 Keith Richards     guitar       0
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-07-16
              • 1970-01-01
              • 2022-04-04
              • 1970-01-01
              • 1970-01-01
              • 2022-10-04
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多