2
votes

Suppose I have the following tibble:

library(tidyverse)
foods <- tibble(
  name  = c("apple", "carrot", "broccoli", "pear", "carrot", "broccoli"),
  color = c("red", "orange", "purple", "green", "orange", "purple"),
  type  = c("fruit", "veggie", "fruit", "fruit", "veggie", "fruit")
)

> foods
# A tibble: 6 x 3
  name     color  type  
  <chr>    <chr>  <chr> 
1 apple    red    fruit 
2 carrot   orange veggie
3 broccoli purple fruit 
4 pear     green  fruit 
5 carrot   orange veggie
6 broccoli purple fruit

As you can see, broccoli's color and type are incorrect here. I can correct it by mutating color and type separately, like this:

> foods %>% 
+   mutate(color = if_else(name == "broccoli", "green", color),
+          type  = if_else(name == "broccoli", "veggie", type))
# A tibble: 6 x 3
  name     color  type  
  <chr>    <chr>  <chr> 
1 apple    red    fruit 
2 carrot   orange veggie
3 broccoli green  veggie
4 pear     green  fruit 
5 carrot   orange veggie
6 broccoli green  veggie

In this example, my solution is basically fine, but repeating the if_else condition becomes annoying if you're trying to mutate many columns at once. Is there a way to specify the condition once and mutate multiple columns? I've done some digging but can't find this question before - I'm sure it's been asked, I'm probably just not wording my search right. So feel free to point me in that direction. I'd prefer a dplyr/tidyverse solution, since that's what I'm familiar with, but other solutions could be useful too. Thanks.

2

2 Answers

0
votes

If we have different values to be updated, map2 would be better

library(dplyr)
library(purrr)
map2_dfc(c('color', 'type'), c('green', 'veggie'), 
       ~ {v1 <- .y
          foods %>% 
               transmute_at(vars(.x), ~ replace(., name == 'broccoli', v1))})%>%
    bind_cols(foods %>% 
               select(name), .)
0
votes

Is it important that broccoli appears in the tibble twice? Or do you just want to update? If the latter

updateFoods <- tibble(
  name = c("broccoli", "eggplant"),
  color = c("green", "purple"),
  type = c("veggie","veggie")
)

foods %>% 
  rbind(updateFoods) %>% 
  group_by(name) %>% 
  summarise_all(~ last(.))

# A tibble: 5 x 3
  name     color  type  
  <chr>    <chr>  <chr> 
1 apple    red    fruit 
2 broccoli green  veggie
3 carrot   orange veggie
4 eggplant purple veggie
5 pear     green  fruit