Создать столбец фиктивной переменной, который указывает, находится ли запись во втором кадре данных? - PullRequest
3 голосов
/ 21 сентября 2019

У меня есть несколько двух кадров данных, 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

IЯ хотел бы добавить столбец к 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, а это не то, что я хочу.(то есть строки Джорджа Харрисона и Пола Маккартни не должны быть в выводе)


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) 

Ответы [ 6 ]

4 голосов
/ 21 сентября 2019
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)
3 голосов
/ 21 сентября 2019

Решение data.table для этого левого соединения будет:

df1[df2, on = "name", nomatch = 0]
2 голосов
/ 21 сентября 2019

Соединение влево, затем изменение, чтобы заменить NA с 0s

> 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

2 голосов
/ 21 сентября 2019

Другое решение:

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
1 голос
/ 23 сентября 2019

safejoin - это пакет, содержащий функции-оболочки dplyr , объединяющие функции, которые могут помочь в этом случае:

Мы хотим eat столбец из df2и замените пропущенные значения на 0, используя параметр .fill.

#install_github("moodymudskipper/safejoin")
library(dplyr, warn.conflicts = FALSE)
library(safejoin)
df1 %>% 
  eat(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
1 голос
/ 21 сентября 2019

Мы также можем match name двух фреймов данных и указать аргумент nomatch равным 0. Присвойте 1, если значение больше 0. Аргумент + в начале преобразует логическое значение в целое число.

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
...