Hmm
Hmm

Reputation: 103

update few values in a data frame column with another data frame column in R

I have two data frames

df1:

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

df2: Name column updated with new names in this data frame. Update the same newnames in df1 data frame.

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

I want to replace the Name in df1 with newNames in df2 based on Id column.

Expected output:

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

Upvotes: 0

Views: 758

Answers (3)

Mikko Marttila
Mikko Marttila

Reputation: 11878

dplyr 1.0.0 added a new experimental function rows_update() that does exactly that:

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

Upvotes: 2

Paul van Oppen
Paul van Oppen

Reputation: 1495

I'd do something like this:

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)

Giving you the required result. You can use merge and if else from base as well.

Or you could do:

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

Both solutions are not robust wrt to the order in which you join or bind the data frames.

Upvotes: 0

Ronak Shah
Ronak Shah

Reputation: 388982

You can use 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

If all the values in df2 are not present in df1 in that case it would be safer to join and select values.

library(dplyr)

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

Upvotes: 0

Related Questions