Problem using the Tidyverse Filter Function to Create My Own Functions

95 Views Asked by At

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

There are 1 best solutions below

0
maike On

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