如何编写支持tidyselect的R函数以移除HLA前缀?
问题:编写支持tidyselect批量选择的HLA前缀移除函数
测试数据
(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" ))
现有手动处理方式
日常使用mutate结合str_replace,配合across批量处理列:
# 处理单列 (test_code <- test %>% mutate(A.1_recipient = str_replace(A.1_recipient, "HLA-", "")) ) # 批量处理指定列范围 (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-", ""))) )
尝试编写的函数及错误
尝试编写支持单列/tidyselect批量选择的函数,但运行报错:
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-", "")) }
错误信息
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.
解决方法
你的函数问题出在mutate的用法上,不需要手动处理eval_select,直接在across里传递...参数即可,这是tidyverse适配tidyselect的标准写法:
正确函数写法
library(dplyr) library(stringr) HLA_prefix_remove <- function(.data, ...) { # 移除HLA前缀,支持单列或tidyselect批量选择列 .data %>% mutate(across(c(...), ~str_replace(., "HLA-", ""))) }
用法演示
# 处理单列 test %>% HLA_prefix_remove(A.1_recipient) # 处理列范围 test %>% HLA_prefix_remove(A.1_recipient:A.2_donor) # 按列名后缀处理 test %>% HLA_prefix_remove(ends_with("recipient"))
错误原因说明
.data代词不支持[索引,只能用[[或$,但此处完全不需要手动操作.data,across已经可以直接接收tidyselect参数。- 你手动调用
eval_select后,错误地把列位置pos传给了str_replace,但str_replace需要的是列的内容而非列位置。
如果需要保留手动处理eval_select的逻辑(比如做额外列校验),可以这样写:
HLA_prefix_remove <- function(.data, ...) { cols <- tidyselect::eval_select(rlang::expr(c(...)), data = .data) .data %>% mutate(across(all_of(cols), ~str_replace(., "HLA-", ""))) }
这里用all_of(cols)把列位置转换为across可识别的选择器。
内容的提问来源于stack exchange,提问作者Nick Brown
相关产品推荐
相关产品推荐

