Home > front end >  Mutate several columns based on one condition
Mutate several columns based on one condition

Time:04-20

I'd like to assign different values to several columns, based on the value in another column, i.e. do a multiple mutate based on a single condition.

For example, I would have a dataframe like this:

df <- tibble(cfr = c("IRL000I12572", "ESP000023522", "ESP000023194"), 
             vessel_name = c("RACHEL JAY", "ALAKRANTXU", "DONIENE"), 
             length = c(NA, NA, 109.30),
             tonnage = c(NA, NA, 3507.00), 
             power = c(NA, NA, 7149.05))

I'd like to manually assign a set of values to length, tonnage, and power when cfr == IRL000I12572, another set of values when cfr == ESP000023522, and keep the given values when cfr == ESP000023194.

Right know, I'm doing it using either an ifelse or case_when statement in my mutate, but I end up with three rows per cfr (and I have many)... For example:

df <- df %>%
mutate(length = ifelse(cfr == "IRL000I12572", 22.5, length),
tonnage = ifelse(cfr == "IRL000I12572", 153.00, tonnage),
power = ifelse(cfr == "IRL000I12572", 370, power))

Is there a way to 'condense' the statement and have only one per cfr value, to assign the three different length, tonnage, and power values in one row?

Thanks!

CodePudding user response:

In base R you could do:

df[df$cfr == "IRL000I12572", -c(1:2)] <- list(22.5, 153.00, 370)

So that

df
#> # A tibble: 3 x 5
#>   cfr          vessel_name length tonnage power
#>   <chr>        <chr>        <dbl>   <dbl> <dbl>
#> 1 IRL000I12572 RACHEL JAY    22.5     153  370 
#> 2 ESP000023522 ALAKRANTXU    NA        NA   NA 
#> 3 ESP000023194 DONIENE      109.     3507 7149.

CodePudding user response:

You can use rows_update() from dplyr. Note that this is marked as an experimental function, so use at your own risk!

library(dplyr)

df <- tibble(cfr = c("IRL000I12572", "ESP000023522", "ESP000023194"), 
             vessel_name = c("RACHEL JAY", "ALAKRANTXU", "DONIENE"), 
             length = c(NA, NA, 109.30),
             tonnage = c(NA, NA, 3507.00), 
             power = c(NA, NA, 7149.05))

df_update <- tibble(cfr = "IRL000I12572",
                    length = 22.5,
                    tonnage = 153.00,
                    power = 370)

df %>% 
  rows_update(df_update, by = "cfr")
# A tibble: 3 x 5
  cfr          vessel_name length tonnage power
  <chr>        <chr>        <dbl>   <dbl> <dbl>
1 IRL000I12572 RACHEL JAY    22.5     153  370 
2 ESP000023522 ALAKRANTXU    NA        NA   NA 
3 ESP000023194 DONIENE      109.     3507 7149.

You can also make use of across to pull from a reference list (or vector). But this would require a different reference table or some other code feature per lookup ID.

x <- list(length = 22.5,
          tonnage = 153.00,
          power = 370)

df %>% 
  mutate(across(names(x), ~ ifelse(cfr == "IRL000I12572", x[[cur_column()]], .)))
  • Related