变量名与数据框列名重名时dplyr::filter失效的原因咨询
循环变量与数据框列名重名时dplyr::filter异常的原因
问题重现
首先定义遍历向量与目标数据框:
# 遍历用的字符串向量 measurements <- c("A","B","C","D") # 构建可复现的tibble数据框 value <- c(1,2,3,4) measurement <- c("A","B","C","D") questiondata <- data.frame(measurement, value) %>% as.tibble()
当循环变量命名为measurement(与数据框列名完全一致)时,dplyr::filter会每次返回整个数据框:
for (measurement in measurements){ print(measurement) print(questiondata %>% dplyr::filter(measurement == measurement)) }
将循环变量改为m后,过滤功能恢复正常:
for (m in measurements){ print(m) print(questiondata %>% dplyr::filter(measurement == m)) }
原因解析
这是dplyr的非标准求值(Non-Standard Evaluation, NSE)机制导致的:
- 在
dplyr::filter()的执行上下文中,R会优先在数据框的内部环境中查找变量,而非全局/循环的外部环境。 - 当你写
measurement == measurement时,两边的measurement都会被解析为数据框自带的measurement列,相当于让列内每个元素和自身比较,结果全为TRUE,因此会返回整个数据框。 - 当循环变量改为
m时,m仅存在于外部循环环境中,dplyr会正确区分数据框的measurement列和循环变量m,完成正常的匹配过滤。
如果一定要使用和列名相同的循环变量,可以用.env显式指定取外部环境的变量:
for (measurement in measurements){ print(measurement) print(questiondata %>% dplyr::filter(measurement == .env$measurement)) }
内容的提问来源于stack exchange,提问作者spleen
相关产品推荐
相关产品推荐

