Home > OS >  How to dynamically pass columns in tidyverse's across
How to dynamically pass columns in tidyverse's across

Time:02-19

Assuming the following data:

df <- data.frame(id     = 1:3,
                 result1 = 4:6,
                 result2 = letters[7:9],
                 result1_label = "test label 1",
                 result2_label = "test label 2")

I now want to create a rowwise(!) list column where I put together result1 with result1_label, and the same for result2.

Now, I can use tidyverse's across to "loop" through my results columns. However, I don't know how I could pass dynamically the respective label.

Here's my idea:

library(tidyverse)
df_new <- df %>%
  rowwise() %>%
  mutate(across(c(result1, result2), ~list(list("answer" = .,
                                                "label"  = sym(paste0(cur_column(),"_label")))),
                .names = "question_{.col}"))

It creates the columns I wanted. However, if you look at the data more closely with, you'll see that it didn't write the actual value from the result1_label column, but instead "symbol result1_label":

str(df_new$question_result1)

    tibble [3 x 1] (S3: rowwise_df/tbl_df/tbl/data.frame)
 $ question_result1:List of 3
  ..$ :List of 2
  .. ..$ answer: int 4
  .. ..$ label : symbol result1_label
  ..$ :List of 2
  .. ..$ answer: int 5
  .. ..$ label : symbol result1_label
  ..$ :List of 2
  .. ..$ answer: int 6
  .. ..$ label : symbol result1_label

Any idea, how I can pass teh actual value for the respective label column?

Note, my real-life example might have hundred or so such columns, that's why I need to automate.

I initially though I'd just pivot_longer my data so that I have one colum for the result and one for the label, but this doesn't work since the respective results columns have different classes (numeric and character).

CodePudding user response:

Use get:

df_new <- df %>%
  rowwise() %>%
  mutate(across(c(result1, result2), ~list(list("answer" = .,
                                                "label"  = get(paste0(cur_column(),"_label")))),
                .names = "question_{.col}"))
> str(df_new$question_result1)
List of 3
 $ :List of 2
  ..$ answer: int 4
  ..$ label : chr "test label 1"
 $ :List of 2
  ..$ answer: int 5
  ..$ label : chr "test label 1"
 $ :List of 2
  ..$ answer: int 6
  ..$ label : chr "test label 1"
  • Related