Assign variable names and their values using an external file

52 Views Asked by At

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"
2

There are 2 best solutions below

0
AnilGoyal On BEST ANSWER

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

2
Carl On

Possible option:

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")

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

lst <- param_file2 |> 
  group_split(model, variable, .keep = FALSE) |> 
  set_names(unique(param_file2$variable)) |> 
  map(\(x) x |> pull(value))

list2env(lst, globalenv())
#> <environment: R_GlobalEnv>

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