在函数与for循环中向dplyr传递列名时结果异常的问题排查
问题解决:dplyr中字符串列名的传递问题
你的代码输出全为0的核心原因是:函数中传入的是字符串类型的列名,但dplyr的函数(如filter、select)默认会把s当成变量名而非字符串对应的列,导致过滤条件s == 1永远不成立,最终结果行数为0。以下是两种可行的修复方案:
方案1:使用.data代词(推荐,代码更简洁)
.data[[s]]可以明确告诉dplyr:从数据框中提取名为s的字符串对应的列。
修改后的函数代码:
cols = c('i', 'a', 'e', 'g','l', 'm', 's', 't') # 两个数据集中的部分列名 number_of_gs <- function(s) { o1_logical %>% filter(.data[[s]] == 1) %>% dplyr::select(name) %>% inner_join(o1, by = "name") %>% # 显式指定连接列,避免歧义 dplyr::select(.data[[s]]) %>% mutate(s_col = strsplit(as.character(.data[[s]]), ", ")) %>% unnest(cols = c(s_col)) %>% nrow() %>% print() } num_os <- function(s) { o1_logical %>% filter(.data[[s]] == 1) %>% dplyr::select(name) %>% nrow() %>% print() } # 循环执行 for (i in cols){ number_of_gs(i) num_os(i) }
方案2:使用rlang::sym()转换为列名符号
通过sym()将字符串转换为dplyr能识别的列名符号,再用!!(解引用)传入函数:
library(rlang) cols = c('i', 'a', 'e', 'g','l', 'm', 's', 't') number_of_gs <- function(s) { col_sym <- sym(s) o1_logical %>% filter(!!col_sym == 1) %>% dplyr::select(name) %>% inner_join(o1, by = "name") %>% dplyr::select(!!col_sym) %>% mutate(s_col = strsplit(as.character(!!col_sym), ", ")) %>% unnest(cols = c(s_col)) %>% nrow() %>% print() } num_os <- function(s) { col_sym <- sym(s) o1_logical %>% filter(!!col_sym == 1) %>% dplyr::select(name) %>% nrow() %>% print() } for (i in cols){ number_of_gs(i) num_os(i) }
关键说明
- 之前尝试的
{{s}}无效,是因为{{}}适用于传递裸列名(比如直接传i而非"i"),而你传入的是字符串,所以{{s}}会把字符串当成字面量,导致filter("i" == 1)这种永远为假的条件。 - 显式指定
inner_join的by = "name"很重要,避免两个数据集有其他同名列时,dplyr自动按所有同名列连接,导致结果不符合预期。
内容的提问来源于stack exchange,提问作者cookiemonster
相关产品推荐
相关产品推荐

