I'm trying to write a function that takes a dataframe and makes a new column where each of it's row values are conditional on columns that contain the strings "bead" and "coefficient" in their column name.
The function would have the following inputs: -data: The dataframe -analyte: a string that is the name of the analyte (e.g. "protein1" or "protein2")
The dataframe has columns like this
id <- c(1,2)
protein1_bead <- c(50,20)
protein1_coef <- c(20,60)
protein2_bead <- c(50,20)
protein2_coef <- c(20,60)
analyte_df <- as.data.frame(cbind(id, protein1_bead, protein1_coef, protein2_bead, protein2_coef))
Here are the steps of the function:
The syntax in the end might be something like:
target_function(data = analyte_df, analyte = "protein1")
I want this:
ID | protein1_bead | protein1_coef | target |
---|---|---|---|
2 | 20 | 60 | re_run |
This is the function I tried to write:
target_function <- function(data, analyte){
target_list <- data %>% select(ID, contains(analyte)) %>%
mutate(target = case_when(grep("bead", names(.)) < 30 & grep("coef", names(.)) > 50 ~ "re_run",
TRUE ~ NA_character_)) %>%
filter(target == "re_run")
return(target_list)
}
But I get the error:
Error in `mutate()`:
! Problem while computing `target = case_when(...)`.
✖ `target` must be size 2 or 1, not 0.
Which I suspect is because I can't use grep and names() inside a case_when like this. I just haven't found an answer yet. Thanks in advance
I think the key here is !!sym(...)
. You can't use a string for a column name, so you have to do a little non-standard eval magic.
library(tidyverse)
target_function <- function(data, analyte){
data |>
select(starts_with(analyte)) |>
mutate(target = case_when(
!!sym(glue::glue("{analyte}_bead")) < 30 &
!!sym(glue::glue("{analyte}_coef")) > 50 ~ "re_run",
TRUE ~ NA_character_
)) |>
filter(!is.na(target))
}
target_function(data = analyte_df, analyte = "protein1")
#> protein1_bead protein1_coef target
#> 1 20 60 re_run