0

I have data like this:

(test <- tribble(
  ~case, ~A.1_recipient, ~A.2_recipient, ~A.1_donor, ~A.2_donor,
  1, "HLA-A2", "HLA-A3", "HLA-A2", "HLA-A68",
  2, "A2", "HLA-A3", "A3", "A69",
  3, "A11", "A24", "HLA-A2", NA,
  4, "A66", NA, "A2", "A24"
  ))

I often use code to remove prefixes from the values:

(test_code <- test
  %>% mutate(A.1_recipient = str_replace(A.1_recipient, "HLA-", ""))
)

I also use tidyselect to apply the function to multiple columns:

(test_code <- test
  %>% mutate(across(A.1_recipient:A.2_donor, ~str_replace(., "HLA-", "")))
)

(test_code <- test
  %>% mutate(across(ends_with("recipient"), ~str_replace(., "HLA-", "")))
)

I would like to develop this into a function that would deal with either a single column input or tidyselect. Using this link (https://cran.r-project.org/web/packages/tidyselect/vignettes/tidyselect.html) I have tried the following function:

HLA_prefix_remove <- function(.data, ...) {
    # Remove any HLA and locus prefixes from typing results.
  expr <- rlang::expr(c(...))
  pos <- eval_select(expr, data = .data)
  .data <- .data %>% 
  mutate(.data[pos], ~str_replace(pos, "HLA-", "")) 
}

Which I try to run with the following code:

(test_function <- test
  %>% HLA_prefix_remove(A.1_recipient)
  )

However, I get the following error:

Error in `mutate()`:
! Problem while computing `..1 = .data[pos]`.
Caused by error in `.data[pos]`:
! `[` is not supported by the `.data` pronoun, use `[[` or $
  instead.
Backtrace:
  1. test %>% HLA_prefix_remove(A.1_recipient)
 10. rlang:::`[.rlang_data_pronoun`(.data, pos)
 Error in mutate(., .data[pos], ~str_replace(pos, "HLA-", "")) : 
Caused by error in `.data[pos]`:
! `[` is not supported by the `.data` pronoun, use `[[` or $
 instead.

Not sure how to write the function to properly pass the arguments through?

Nick Brown
  • 55
  • 6

2 Answers2

2

Use c(...) like this:

library(dplyr)
library(stringr)

HLA_prefix_remove2 <- function(.data, ...) {
  .data %>% mutate(across(c(...), ~str_replace(., "HLA-", "")))
}

HLA_prefix_remove2(test, A.1_recipient:A.2_donor)
HLA_prefix_remove2(test, ends_with("recipient"))
HLA_prefix_remove2(test, c(A.1_recipient, A.2_recipient))
HLA_prefix_remove2(test, A.1_recipient, A.2_recipient)

If having a single second argument is ok then this would also work:

HLA_prefix_remove3 <- function(.data, sel) {
  .data %>% mutate(across({{sel}}, ~str_replace(., "HLA-", "")))
}

HLA_prefix_remove3(test, A.1_recipient:A.2_donor)
HLA_prefix_remove3(test, ends_with("recipient"))
HLA_prefix_remove3(test, c(A.1_recipient, A.2_recipient))
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
1

We may change the function to

library(rlang)
library(dplyr)
library(purrr)
library(stringr)
HLA_prefix_remove <- function(.data, ...) {
      colnms <- map_chr(rlang::ensyms(...), as_string)
     .data %>% 
         mutate(across(all_of(colnms), ~str_replace(.x, "HLA-", "")))
}

-testing

test %>%
    HLA_prefix_remove(A.1_recipient)
# A tibble: 4 × 5
   case A.1_recipient A.2_recipient A.1_donor A.2_donor
  <dbl> <chr>         <chr>         <chr>     <chr>    
1     1 A2            HLA-A3        HLA-A2    HLA-A68  
2     2 A2            HLA-A3        A3        A69      
3     3 A11           A24           HLA-A2    <NA>     
4     4 A66           <NA>          A2        A24   
test %>%
   HLA_prefix_remove(A.1_recipient, A.2_recipient)
# A tibble: 4 × 5
   case A.1_recipient A.2_recipient A.1_donor A.2_donor
  <dbl> <chr>         <chr>         <chr>     <chr>    
1     1 A2            A3            HLA-A2    HLA-A68  
2     2 A2            A3            A3        A69      
3     3 A11           A24           HLA-A2    <NA>     
4     4 A66           <NA>          A2        A24         
akrun
  • 874,273
  • 37
  • 540
  • 662