Automated way to selectively update cells of dataframe by row id

Say you have a dataframe:

original_values <- 
    tibble(
        id = c("50.0", "55.0", "63.0", "65.0", "68.0"),
        dest = rep("dummy", 5),
        date = as_date(rep("2020-01-01", 5)),
        friend = rep("Steve")
    )

Imagine mine is much bigger, but this is just for illustration.

For a subset of rows, I want to update certain cells with values stored in a new dataframe.


value_corrections <-
    tibble(
        id = c("50.0", "63.0", "68.0"),
        destination = c("Unknown", "Rush Oak Park ED", "Unknown"),
        date = as_date(c("2021-06-27", "2021-07-12", "2021-08-09"))
    )

Is there a succinct way to do this programmatically?

I've tried this a few different ways, but most recently:

update_discharges <- function(a_tibble, an_id, a_destination, a_date){
    a_tibble[a_tibble$id == an_id, 'dest'] <- a_destination
    a_tibble[a_tibble$id == an_id, 'date'] <- a_date
}

for(i in seq_along(value_corrections)) {
    update_discharges(
        a_tibble = original_values,
        an_id = value_corrections$an_id[[i]],
        a_destination = value_corrections$a_destination[[i]],
        a_date = value_corrections$a_date[[i]]
    )
}

Could you do it with a join? e.g.,

library(tidyverse)
library(lubridate)
#> 
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:base':
#> 
#>     date, intersect, setdiff, union

original_values <- 
  tibble(
    id = c("50.0", "55.0", "63.0", "65.0", "68.0"),
    dest = rep("dummy", 5),
    date = as_date(rep("2020-01-01", 5)),
    friend = rep("Steve")
  )

value_corrections <-
  tibble(
    id = c("50.0", "63.0", "68.0"),
    destination = c("Unknown", "Rush Oak Park ED", "Unknown"),
    date = as_date(c("2021-06-27", "2021-07-12", "2021-08-09"))
  )

original_values %>% 
  left_join(value_corrections, by = "id", suffix = c("","_new")) %>% 
  mutate(
    dest = if_else(
      !is.na(destination), destination, dest
    ),
    date = if_else(
      !is.na(date_new), date_new, date
    )
  ) %>% 
  select(-destination, -date_new)
#> # A tibble: 5 x 4
#>   id    dest             date       friend
#>   <chr> <chr>            <date>     <chr> 
#> 1 50.0  Unknown          2021-06-27 Steve 
#> 2 55.0  dummy            2020-01-01 Steve 
#> 3 63.0  Rush Oak Park ED 2021-07-12 Steve 
#> 4 65.0  dummy            2020-01-01 Steve 
#> 5 68.0  Unknown          2021-08-09 Steve

Created on 2021-12-20 by the reprex package (v2.0.1)

1 Like

Awesome, thank you! I don't use joins enough!

There is an experimental function in tidyr for that rows_update()

1 Like

Oooh! I love it, nice and succinct!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.