Search code examples
rdplyrpurrr

Assign variable names and their values using an external file


I am currently reading data from an external file that looks like this:

param_file <- tribble(
  ~model, ~variable, ~value,
  "BAX", "year", "2023",
  "BAX", "version", "Saint_XL, Sinner_XY",
  "BAX", "metric", "ATE, OFCE",
  "LAX", "time", "2024",
  "LAX", "model2", "Saint_XX, Sinner_XW",
  "LAX", "method", "TEA, CEOF")

I am then separating the rows and filtering out for the model I would like to run, which is BAX in this case:

param_file2 <- param_file %>% 
  separate_rows(value, sep = ",") %>% 
  mutate(value = trimws(value)) %>% 
  filter(model == "BAX")

Which looks like this:

  model variable value    
  <chr> <chr>    <chr>    
1 BAX   year     2023     
2 BAX   version  Saint_XL 
3 BAX   version  Sinner_XY
4 BAX   metric   ATE      
5 BAX   metric   OFCE   

I was wondering if there was a way to automatically assign the variable and its values as character vectors:

So for the BAX model these would be:

year <- param_file2 %>% filter(variable == "year") %>% pull(value)
version <- param_file2 %>% filter(variable == "version") %>% pull(value)
metric <- param_file2 %>% filter(variable == "metric") %>% pull(value)

and the LAX model:

time <- param_file2 %>% filter(variable == "time") %>% pull(value)
model2 <- param_file2 %>% filter(variable == "model2") %>% pull(value)
method <- param_file2 %>% filter(variable == "method") %>% pull(value)

These give me the desired answer, but I need to write a new line of code each time I want to define a new variable - for each model. I was wondering if there is a way of assigning whatever is read in the variable column to its corresponding value(s) without having to write a new line of code each time.

i.e. If a 2 new lines appeared in the external file as follows:

param_file <- tribble(
  ~model, ~variable, ~value,
  "BAX", "pasta", "sauce",
  "BAX", "jalapenos", "are, spicy")

Then I would like the 2 new variables defined as follows (without having to explicitly assign these with a new line)... ideally using a function or a purrr loop for example:

> pasta
[1] "sauce"
> jalapenos
[1] "are"   "spicy"

Solution

  • The question is a good example to use base R's assign and purrr::walk series of functions.

    This tidyverse strategy will work, particularly as OP has tagged purrr in post. (I am using purrr::walk2 here, as there would be no output and code will silently create new variables as desired).

    library(tidyverse)
    param_file <- tribble(
      ~model, ~variable, ~value,
      "BAX", "year", "2023",
      "BAX", "version", "Saint_XL, Sinner_XY",
      "BAX", "metric", "ATE, OFCE",
      "LAX", "time", "2024",
      "LAX", "model2", "Saint_XX, Sinner_XW",
      "LAX", "method", "TEA, CEOF")
    
    library(magrittr, warn.conflicts = F)
    
    # Check that no other variable exists other than data
    ls()
    #> [1] "param_file"
    
    param_file %>% 
      mutate(value = map(value, ~unlist(str_split(.x, pattern = ", ")))) %$% 
      purrr::walk2(variable, value, ~ assign(.x, .y, envir = .GlobalEnv))
    
    # Recheck that variables have been created
    ls()
    #> [1] "method"     "metric"     "model2"     "param_file" "time"      
    #> [6] "version"    "year"
    
    #print first one to check
    get(ls()[1])
    #> [1] "TEA"  "CEOF"
    

    Created on 2024-03-20 with reprex v2.0.2