обновите несколько значений в столбце фрейма данных другим столбцом фрейма данных в R

#r

#r

Вопрос:

У меня есть два фрейма данных

df1:

 Id     Name        Column3
3      name1        fdf       
12     name343      dfd
32     name65       sis
45     name23       rir
16     name98       tit
  

df2: столбец Name обновлен новыми именами в этом фрейме данных. Обновите те же новые имена в фрейме данных df1.

 Id     Name        Column3
12     newName1     dfd
45     newName34    rir
16     newName111   tit
  

Я хочу заменить имя в df1 новыми именами в df2 на основе столбца Id.

Ожидаемый результат:

     Id     Name          Column3
    3      name1          fdf       
    12     newName1       dfd
    32     name65         sis
    45     newName34      rir
    16     newName111     tit
  

Ответ №1:

dplyr 1.0.0 добавил новую экспериментальную функцию rows_update() , которая делает именно это:

 library(tidyverse)

df1 <- read_table("Id     Name        Column3
3      name1        fdf       
12     name343      dfd
32     name65       sis
45     name23       rir
16     name98       tit")

df2 <- read_table("Id     Name        Column3
12     newName1     dfd
45     newName34    rir
16     newName111   tit")

df1 %>% rows_update(df2, by = "Id")
#> # A tibble: 5 x 3
#>      Id Name       Column3
#>   <dbl> <chr>      <chr>  
#> 1     3 name1      fdf    
#> 2    12 newName1   dfd    
#> 3    32 name65     sis    
#> 4    45 newName34  rir    
#> 5    16 newName111 tit
  

Ответ №2:

Вы можете использовать match :

 df1$Name[match(df2$Id, df1$Id)] <- df2$Name
df1

#  Id       Name Column3
#1  3      name1     fdf
#2 12   newName1     dfd
#3 32     name65     sis
#4 45  newName34     rir
#5 16 newName111     tit
  

Если все значения в df2 отсутствуют в df1 , в этом случае было бы безопаснее объединить и выбрать значения.

 library(dplyr)

df1 %>%
  left_join(df2, by = 'Id') %>%
  mutate(Name = coalesce(Name.y, Name.x)) %>%
  select(Id, Name, Column3 = Column3.x)
  

Комментарии:

1. Здесь я привел только 3 столбца, в моем случае у меня 60 столбцов, запись всех этих 60 столбцов в select не будет хорошей. есть ли какая-либо альтернатива для выбора всех столбцов

2. select используется только для select столбцов. Требуемый ответ содержится в самом mutate шаге. Если столбцов много, то вы можете использовать select(Id, Name, matches('\.x$')) для выбора только столбцов из df1 .

Ответ №3:

Я бы сделал что-то вроде этого:

 library(dplyr)
data <- data1 %>%
  left_join(data2, by = "Id") %>%
  mutate(Name = ifelse(is.na(Name.y), Name.x, Name.y),
         Col3 = ifelse(is.na(Col3.y), Col3.x, Col3.y)) %>%
  select(Id, Name, Col3)
  

Что даст вам требуемый результат. Вы также можете использовать merge и if else from base.

Или вы могли бы сделать:

 data <- bind_rows(data1, data2) %>%
  group_by(Id) %>% 
  slice(n()) 
  

Оба решения не являются надежными по отношению к порядку, в котором вы соединяете фреймы данных.