Home > Enterprise >  How can I force R to use an object's value, not the literal object name?
How can I force R to use an object's value, not the literal object name?

Time:07-16

long-time lurker, first-time poster.

I'm trying to edit an existing script so that I can use a variable to easily change some of the options in my analysis in order to conduct a sensitivity analysis. In this specific example, I'm trying to use an object so that I can easily change which column I'm calling. The columns contain categorical plant traits, and if a plant has two traits, I split its value between both of those traits.

Here is some example data (note that NumTraits gets derived earlier based on which Trait column I want to use, in this example it is Trait1):

Plant Number Value Trait1 Trait2 NumTraits
1 10 A A 1
2 20 B A B 1
3 15 A B A B 2
4 10 B B 1

My existing code reads:

    split.data <- data %>%
    mutate(NewValue = Value/NumTraits) %>%
    tidyr::separate_rows(Trait1, sep = "[ ]") %>%
    group_by(Trait1) %>%
    summarise(NewValue = sum(Value), .groups = 'drop')

This produces the desired output, which is:

| PlantNumber | Value | Trait1 | Trait2 | NumTraits | | ----------- | ----- | ------ | ------ | --------- | | 1 | 10 | A | A | 1 | | 2 | 20 | B | A B | 1 | | 3 | 7.5 | A | A B | 2 | | 4 | 10 | B | B | 1 | | 3 | 7.5 | B | A B | 2 | (note that normally the two PlantNumber = 3 rows would be adjacent, but for some reason StackOverflow didn't accept that formatting)

I would like to have an object, say trait.to.use <- "Trait1", that I can put in place of Trait1 above to easily switch between Trait1 and Trait2 throughout my code. However, if I just replace Trait1 with trait.to.use in the above code, it gives me an error because "trait.to.use" is not a column in my data. I tried trait.to.use[1] and all_of(trait.to.use), but while they return "Trait1" the code doesn't split the values and the resulting Value column is just "Trait1" every line.

How can I pass the column name in an object and get it to produce the desired output? Thanks in advance.

CodePudding user response:

Just use get()

trait.to.use <- "Trait1"

split.data <- data %>%
    mutate(NewValue = Value/NumTraits) %>%
    tidyr::separate_rows(get(trait.to.use), sep = "[ ]") %>%
    group_by(get(trait.to.use)) %>%
    summarise(NewValue = sum(Value), .groups = 'drop')

CodePudding user response:

You can use !!sym to make it symbol

trait.to.use <- c("Trait1" , "Trait2") 

data %>%
    mutate(NewValue = Value/NumTraits) %>%
    tidyr::separate_rows(!!sym(trait.to.use[1]), sep = "[ ]") %>%
    group_by(!!sym(trait.to.use[1])) %>%
    summarise(NewValue = sum(Value), .groups = 'drop')

  • output
# A tibble: 2 × 2
  Trait1 NewValue
  <chr>     <int>
1 A            25
2 B            45

and then you can just change trait.to.use[1] to trait.to.use[2]

  • Related