0

I appreciate any help that can be given. I am working with a data set on bacterial growth. I have collected the data, which has eight variables, and used 'pivot_longer' for optimal plotting. I have three different treatments: experimental, negative control, and positive control. I am trying to write a function that will quickly plot the data as long as I provide the treatment type as an argument in the function.

I am having particular issue with the tidyverse filter function. I am aware that I cannot simply pass "experimental" or experimental as an argument. I understand that I must use either {{}} or that I must incorporate quosures. I looked at Hadley Wickham's article on programming with dplyr and still cannot figure it out.

The main error I keep getting is:

Error in filter(): ℹ In argument: Treatment == Experimental. Caused by error: ! object 'Experimental' not found

If I use deparse and substitute like in this thread I get a different error

Error in seq.default(min(fulldata$Timepoint), max(fulldata$Timepoint), : 'from' must be a finite number In addition: Warning messages: 1: In min(fulldata$Timepoint) : no non-missing arguments to min; returning Inf 2: In max(fulldata$Timepoint) : no non-missing arguments to max; returning -Inf

The first code block shown is where I am stuck and the second code block is how my code has been written without using the function which works perfectly. I think the solution is quite simple, but I am very lost and any help would be appreciated.

plot.RAPTR <- function(x) {
  type <- enquo(x)
  print(type)
  readydata %>% 
    filter(Treatment == UQ(type)) %>%
    group_by(Construct, Replicate, Timepoint, Media, Treatment) %>%
    summarise(avg.abs = mean(Absorbance), std.abs = sd(Absorbance)) %>%
    ggplot(aes(x = Timepoint, y = avg.abs, color = Construct)) +
    geom_errorbar(aes(ymin=avg.abs-std.abs, ymax=avg.abs+std.abs), width=.2, linetype = "dashed")+ 
    geom_point(size=2)+
    labs(title = "EW11 Growth with RAPTR", y = expression("OD"[600]), x = "Timepoint (Hr)",   color = "Treatment")+
    facet_wrap(~Media, ncol = 2) +
    Theme + 
    scale_colour_brewer(palette="Set1")
  scale_x_continuous(breaks = round(seq(min(fulldata$Timepoint), max(fulldata$Timepoint), by = 5),1))+
    scale_y_continuous(breaks = round(seq(min(fulldata$Absorbance), max(fulldata$Absorbance), by = .2),1))
}
   
readydata %>% 
   filter(Treatment == "Experimental") %>%
  group_by(Construct, Replicate, Timepoint, Media, Treatment) %>%
  summarise(avg.abs = mean(Absorbance), std.abs = sd(Absorbance)) %>%
  ggplot(aes(x = Timepoint, y = avg.abs, color = Construct)) +
  geom_errorbar(aes(ymin=avg.abs-std.abs, ymax=avg.abs+std.abs), width=.2, linetype = "dashed")+ 
  geom_point(size=2)+
  labs(title = "EW11 Growth with RAPTR", y = expression("OD"[600]), x = "Timepoint (Hr)",   color = "Treatment")+
  facet_wrap(~Media, ncol = 2) +
  Theme + 
  scale_colour_brewer(palette="Set1")
   scale_x_continuous(breaks = round(seq(min(fulldata$Timepoint), max(fulldata$Timepoint), by = 5),1))+
   scale_y_continuous(breaks = round(seq(min(fulldata$Absorbance), max(fulldata$Absorbance), by = .2),1))
 
  • 2
    It's easier to help you if you include a simple [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with sample input and desired output that can be used to test and verify possible solutions. Remove any code that's not essential to replicating the error (usually themes just add noise unless your problem is specifically with the theme.) Where are you actually calling the `plot.RAPTR` function? – MrFlick Jun 30 '23 at 19:03
  • 3
    Since you are just passing in a string, i.e. I assume you want to call `plot.RAPRT("Experimental")`, I *think* you can just use `filter(Treatment == x)` directly. It's easier to help if you provide a simple reproducible example (e.g. use `mtcars` as your dataset, and remove all the code from the function unrelated to your actual problem). – Axeman Jun 30 '23 at 19:04

1 Answers1

0

You were right about the embracing part ('{{}}'), I've shown it in the first option. I also added a more general version on how to pass filters, see option 2. As mentioned before, answers can be a lot more specific (and quicker) if you add minimal reproducible examples to your questions.

require(tibble)
#> Loading required package: tibble
require(rlang)
#> Loading required package: rlang
require(dplyr)
#> Loading required package: dplyr
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
require(purrr)
#> Loading required package: purrr
#> 
#> Attaching package: 'purrr'
#> The following objects are masked from 'package:rlang':
#> 
#>     %@%, flatten, flatten_chr, flatten_dbl, flatten_int, flatten_lgl,
#>     flatten_raw, invoke, splice
require(stringr)
#> Loading required package: stringr


# OPTION 1: passing e.g. 'experimental' as the value of the column you are filtering on
filter.mtcars <- function(x){
  
    data.full <- mtcars %>% 
      rownames_to_column('car') %>% 
      mutate(brand = map_chr(car, ~ str_split(.x, ' ')[[1]][1]), .after = 'car') 
    
    data.full %>% 
      filter(brand %in% {{x}})
    
  }

filter.mtcars(c('Merc', 'Lotus'))
#>            car brand  mpg cyl  disp  hp drat    wt qsec vs am gear carb
#> 1    Merc 240D  Merc 24.4   4 146.7  62 3.69 3.190 20.0  1  0    4    2
#> 2     Merc 230  Merc 22.8   4 140.8  95 3.92 3.150 22.9  1  0    4    2
#> 3     Merc 280  Merc 19.2   6 167.6 123 3.92 3.440 18.3  1  0    4    4
#> 4    Merc 280C  Merc 17.8   6 167.6 123 3.92 3.440 18.9  1  0    4    4
#> 5   Merc 450SE  Merc 16.4   8 275.8 180 3.07 4.070 17.4  0  0    3    3
#> 6   Merc 450SL  Merc 17.3   8 275.8 180 3.07 3.730 17.6  0  0    3    3
#> 7  Merc 450SLC  Merc 15.2   8 275.8 180 3.07 3.780 18.0  0  0    3    3
#> 8 Lotus Europa Lotus 30.4   4  95.1 113 3.77 1.513 16.9  1  1    5    2

# OPTION 2: passing the full filter expression(s) for more flexibility
filter.mtcars <- function(x = NULL){
  
  data.full <- mtcars %>% 
    rownames_to_column('car') %>% 
    mutate(brand = map_chr(car, ~ str_split(.x, ' ')[[1]][1]), .after = 'car') 
  
  if(is.null(x)){ 
    data.full 
  }else{
    data.full %>% 
      filter(!!! rlang::parse_exprs(x))
  }
  
  
}

filter.mtcars(c("brand == 'Merc'", "mpg > 17"))
#>          car brand  mpg cyl  disp  hp drat   wt qsec vs am gear carb
#> 1  Merc 240D  Merc 24.4   4 146.7  62 3.69 3.19 20.0  1  0    4    2
#> 2   Merc 230  Merc 22.8   4 140.8  95 3.92 3.15 22.9  1  0    4    2
#> 3   Merc 280  Merc 19.2   6 167.6 123 3.92 3.44 18.3  1  0    4    4
#> 4  Merc 280C  Merc 17.8   6 167.6 123 3.92 3.44 18.9  1  0    4    4
#> 5 Merc 450SL  Merc 17.3   8 275.8 180 3.07 3.73 17.6  0  0    3    3

Created on 2023-07-03 with reprex v2.0.2

maike
  • 220
  • 1
  • 6