Home > OS >  How to evaluate variable names in a vector of pasted strings
How to evaluate variable names in a vector of pasted strings

Time:06-25

I have an example df:

df <- data.frame(
Date1 = as.Date(c("2010-09-10", "2015-12-03")),
Date2 = as.Date(c("2012-09-10", "2016-12-03")),
Selected =  c("Date1", "Date1, Date2"),
Value = c("2010-09-10", "2015-12-03, 2016-12-03"))

  Date1      Date2      Selected     Value                 
1 2010-09-10 2012-09-10 Date1        2010-09-10            
2 2015-12-03 2016-12-03 Date1, Date2 2015-12-03, 2016-12-03

and I want to be able to create/mutate the new column 'Value' that evaluates whatever column names are in the 'Selected' column. I could use get() if the string in 'Selected' was just a single column name but it could be a concatenation of variable names separated by a comma which is where I'm stuck on how to evaluate.

CodePudding user response:

You can do in base R:

columns <- strsplit(df$Selected, ", ")
df$Value <- sapply(1:nrow(df), function(n) paste(format(df[n, columns[[n]]]), collapse = ", "))

CodePudding user response:

1) For each word in Selected get that column name and replace the name in the string with the value of that column in the same row using gsubfn. gsubfn is like gsub except the replacement string can be a replacement function to which the match to the capture group in the regex (the part in parentheses) in the pattern is input and replaced with the output of the function. The function can be specified using formula notation as we do here.

library(dplyr)
library(gsubfn)

df %>%
  rowwise %>%
  mutate(Value=gsubfn("(\\w )", ~ format(get(x)), Selected)) %>%
  ungroup
## # A tibble: 2 x 4
##   Date1      Date2      Selected     Value                 
##   <date>     <date>     <chr>        <chr>                 
## 1 2010-09-10 2012-09-10 Date1        2010-09-10            
## 2 2015-12-03 2016-12-03 Date1, Date2 2015-12-03, 2016-12-03

2) This can also be done using just gsubfn.

library(gsubfn)

nr <- nrow(df)
df |>
  by(1:nr, transform, Value = gsubfn("(\\w )", ~ format(get(x)), Selected)) |>
  do.call(what = "rbind")
##        Date1      Date2     Selected                  Value
## 1 2010-09-10 2012-09-10        Date1             2010-09-10
## 2 2015-12-03 2016-12-03 Date1, Date2 2015-12-03, 2016-12-03

CodePudding user response:

A possible solution, based on tidyverse:

library(tidyverse)

df %>% 
  separate_rows(Selected, sep = ",\\s*") %>% 
  rowwise %>% 
  mutate(Value = cur_data()[[Selected]]) %>% 
  group_by(Date1, Date2) %>% 
  summarise(Selected = str_c(Selected, collapse = ", "), 
            Value = str_c(Value, collapse = ", "), .groups = "drop")

#> # A tibble: 2 × 4
#>   Date1      Date2      Selected     Value                 
#>   <date>     <date>     <chr>        <chr>                 
#> 1 2010-09-10 2012-09-10 Date1        2010-09-10            
#> 2 2015-12-03 2016-12-03 Date1, Date2 2015-12-03, 2016-12-03

A more succinct one:

library(tidyverse)

df %>%
  rowwise %>%
  mutate(Value = map(str_split(Selected, ", "), ~ cur_data()[.x]),
         Value = reduce(Value, c) %>% str_c(collapse=", ")) %>%
  ungroup

#> # A tibble: 2 × 4
#>   Date1      Date2      Selected     Value                 
#>   <date>     <date>     <chr>        <chr>                 
#> 1 2010-09-10 2012-09-10 Date1        2010-09-10            
#> 2 2015-12-03 2016-12-03 Date1, Date2 2015-12-03, 2016-12-03
  • Related