Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Create new column based on existing columns whose names are stored in another column (dplyr)

Consider the following dataset:

df <- tibble(v1 = 1:5, v2= 101:105, v3 = c("v1", "v2", "v1", "v2", "v1"))

# A tibble: 5 × 3
     v1    v2 v3   
  <int> <int> <chr>
1     1   101 v1   
2     2   102 v2   
3     3   103 v1   
4     4   104 v2   
5     5   105 v1  

I would like to generate a new column that takes values from either v1 or v2, depending on which column is listed in v3.

    # A tibble: 5 × 4
     v1    v2 v3       v4
  <int> <int> <chr> <dbl>
1     1   101 v1        1
2     2   102 v2      102
3     3   103 v1        3
4     4   104 v2      104
5     5   105 v1        5

Normally, I would use if_else, or if I had more cases, case_when. However, I have a lot of columns, so I’d rather not have a case_when statement that’s many lines long. Is there a way to get R to interpret the values in v3 as column names? I’ve tried embracing the expression with {{ }} and using the .data[[ ]], but I can’t seem to figure out the correct syntax.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

A tidyverse option would be rowwise with extraction using cur_data()

library(dplyr)
df %>% 
  rowwise %>%
  mutate(v4 = cur_data()[[v3]]) %>% 
  ungroup
# A tibble: 5 × 4
     v1    v2 v3       v4
  <int> <int> <chr> <int>
1     1   101 v1        1
2     2   102 v2      102
3     3   103 v1        3
4     4   104 v2      104
5     5   105 v1        5

Or a compact approach would be get after rowwise

df %>%
  rowwise %>%
  mutate(v4 = get(v3)) %>%
  ungroup

Or in base R, use row/column indexing for faster execution

df$v4 <- as.data.frame(df[1:2])[cbind(seq_len(nrow(df)), 
      match(df$v3, names(df)))]
df$v4
[1]   1 102   3 104   5
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading