Home > Enterprise >  Create several new variables using a vector of names and a vector for computation within dplyr::muta
Create several new variables using a vector of names and a vector for computation within dplyr::muta

Time:04-30

I'd like to create several new columns. They should take their names from one vector and they should be computed by taking one column in the data and dividing it by another.

mytib <- tibble(id = 1:2, value1 = c(4,6), value2 = c(42, 5), total = c(2,2))
myvalues <- c("value1", "value2")
mynames  <- c("value1_percent", "value2_percent")

mytib %>%
     mutate({{ mynames }} := {{ myvalues }}/total)

Here, I get the error message, which makes me think that the curly-curly operator is misplaced

Error in local_error_context(dots = dots, .index = i, mask = mask) : promise already under evaluation: recursive default argument reference or earlier problems?

I'd like to calculate the percentage columns programmatically (since I have many such columns in my data).

The desired output should be equivalent to this:

mytib %>%
    mutate( "value1_percent" = value1/total, "value2_percent" = value2/total)

which gives

# A tibble: 2 × 6
     id value1 value2 total value1_percent value2_percent
  <int>  <dbl>  <dbl> <dbl>          <dbl>          <dbl>
1     1      4     42     2              2           21  
2     2      6      5     2              3            2.5

CodePudding user response:

You could use across and construct the new names in its .names argument:

library(dplyr)

mytib %>%
    mutate(across(starts_with('value'),
                  ~ .x / total,
                  .names = "{.col}_percent"
                  ))

CodePudding user response:

I prefer mutate(across(...)) in this case. To make your idea work, try reduce2() from purrr.

library(dplyr)
library(purrr)

reduce2(mynames, myvalues,
        ~ mutate(..1, !!..2 := !!sym(..3)/total), .init = mytib)

# # A tibble: 2 x 6
#      id value1 value2 total value1_percent value2_percent
#   <int>  <dbl>  <dbl> <dbl>          <dbl>          <dbl>
# 1     1      4     42     2              2           21  
# 2     2      6      5     2              3            2.5

The above code is actually a shortcut of:

mytib %>%
  mutate(!!mynames[1] := !!sym(myvalues[1])/total,
         !!mynames[2] := !!sym(myvalues[2])/total)
  • Related