如何将dplyr转换命令改写为可循环调用的base R自定义函数
问题说明
原有自定义函数运行不生效,由三个核心问题导致:
- 函数内部完成数据修改后,没有返回最终的 data.frame 对象,R 函数默认仅返回最后一行表达式的执行结果,赋值操作本身不会向外输出修改后的数据
- dplyr 采用非标准求值逻辑,直接在判断条件中写参数名、传入字符串格式列名时,无法定位到数据框内的实际列
- R 不会直接修改函数外部的原对象,函数返回的修改结果需要重新赋值才能持久保存
可用函数实现
使用 dplyr 提供的 .data 代词引用传入的字符串列名,兼容性适配循环调用场景,函数末尾直接返回处理后的数据:
library(dplyr) FunXOR <- function(df, X1, X2) { df %>% mutate(XOR_inter = case_when( .data[[X1]] == 0 & .data[[X2]] == 0 ~ 0, .data[[X1]] == 0 & .data[[X2]] == 1 ~ 1, .data[[X1]] == 0 & .data[[X2]] == 2 ~ 0, .data[[X1]] == 1 & .data[[X2]] == 0 ~ 1, .data[[X1]] == 1 & .data[[X2]] == 1 ~ 0, .data[[X1]] == 1 & .data[[X2]] == 2 ~ 1, .data[[X1]] == 2 & .data[[X2]] == 0 ~ 0, .data[[X1]] == 2 & .data[[X2]] == 1 ~ 1, .data[[X1]] == 2 & .data[[X2]] == 2 ~ 0 )) }
逻辑简化方案
观察赋值规则可以发现:当两个列的取值奇偶性不同时返回1,相同时返回0,完全匹配异或逻辑,不需要逐一枚举9种组合,可大幅简化代码,降低出错概率:
FunXOR <- function(df, X1, X2) { df %>% mutate(XOR_inter = as.integer((.data[[X1]] %% 2) != (.data[[X2]] %% 2))) }
调用方法
单组场景调用时,需要将函数返回结果重新赋值给原对象才能保存修改:
XOR1 <- FunXOR(XOR1, "chr18.27348077_G", "chr18.32316331_A")
循环批量计算多组位点的示例:
# 提前存储所有需要计算的位点对 snp_pair_list <- list( c("chr18.27348077_G", "chr18.32316331_A"), c("chr18.位点1", "chr18.位点2") ) # 循环生成带区分后缀的互作列 for (idx in seq_along(snp_pair_list)) { snp1 <- snp_pair_list[[idx]][1] snp2 <- snp_pair_list[[idx]][2] new_col <- paste0("XOR_inter_", idx) XOR1 <- XOR1 %>% mutate({{new_col}} := as.integer((.data[[snp1]] %% 2) != (.data[[snp2]] %% 2))) }
内容的提问来源于stack exchange,提问作者Melderon
相关产品推荐
相关产品推荐

