You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写支持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"))

错误原因说明

  1. .data代词不支持[索引,只能用[[或$,但此处完全不需要手动操作.data,across已经可以直接接收tidyselect参数。
  2. 你手动调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 13:06:17