向dplyr::slice_max()的order_by传字符串列名异常,求解决方法
如何在dplyr::slice_max()中传入字符串格式的列名作为order_by参数?
问题重现
用iris数据集测试时,直接写列名能得到预期的5行结果:
library(dplyr) # 正常工作:返回Sepal.Length最大的5行 i <- iris %>% slice_max(n = 5, order_by = Sepal.Length)
但用字符串变量lastcol <- first(colnames(iris))(值为"Sepal.Length")传入时,出现异常或报错:
# 异常:仅返回1行 i <- iris %>% slice_max(n = 5, order_by = lastcol) # 异常:仅返回1行 i <- iris %>% slice_max(n = 5, order_by = !!lastcol) # 报错:`:=` can only be used within a quasiquoted argument i <- iris %>% slice_max(n = 5, order_by := .data[[lastcol]])
错误原因分析
- 直接传字符串变量:
order_by = lastcol时,dplyr会把lastcol的字符串值("Sepal.Length")当成常量,所有行的排序键都是同一个字符串,因此只会返回任意1行(因为所有行排序优先级相同)。 - 用!!解引用字符串:
!!lastcol只是把字符串本身展开,和直接传变量的问题一样,排序键还是常量字符串,而非对应列的数值。 - 错误使用:=:
:=是tidyverse中用于动态定义参数名称(比如mutate的新列名)的语法,slice_max的order_by是普通参数,不能用这个赋值方式,所以报错。
正确实现方式
方法1:使用.data代词
.data[[lastcol]]明确告诉dplyr从数据框中提取名为lastcol对应字符串的列:
i <- iris %>% slice_max(n = 5, order_by = .data[[lastcol]])
方法2:用sym()转换为符号后解引用
先把字符串转换成dplyr能识别的列名符号,再用!!解引用:
library(rlang) i <- iris %>% slice_max(n = 5, order_by = !!sym(lastcol))
方法3:使用pick()(dplyr 1.1.0+支持)
pick()可以直接根据字符串选择列,返回的是 tibble,slice_max会自动处理:
i <- iris %>% slice_max(n = 5, order_by = pick(lastcol))
内容的提问来源于stack exchange,提问作者Timm S.
相关产品推荐
相关产品推荐

