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()]], .)))