如何解决将整洁的选择参数转换为字符向量
我正在努力将整齐的选择样式函数参数转换为字符向量。
f <- function(d,cols1,cols2) {
<do something useful with d>
<some magic>
}
f(iris,c(Sepal.Length,Species),Petal.Width)
# [1] "Sepal.Length" "Species" "Petal.Width"
这是一个激励人的例子。
比方说,我有一个函数可以创建两个data.frame
并将它们连接在一起。 data.frame
中的一个计算时间很长,因此我想提供一个提供预先计算的data.frame的选项。
我在这里使用拥抱来进行整洁的评估。看一个最小的例子:
my_func <- function(df,cols2,df2=NULL) {
df1 <- df %>%
do_something(across({{cols1}})
if (!is.null(df2) {
# 1. here I would like to check column names of df2
} else {
df2 <- df %>%
do_something_very_slow(across({{cols2}})
}
# 2. here I would like to provide by=c(cols1,cols2)
full_join(df1,df2)
}
# I am using tidy select to pass column names to the function.
result <- my_func(df,c(a,b),c)
现在,我想对这段代码进行两项改进。
- 在#1中,我想验证precomputed_df是否具有它需要的所有列(即:a,b和c)。直接的方法是将c(col1,col2)转换为字符向量。但这当然会导致错误。我看到的其他替代方法是尝试将
select()
与tryCatch()
一起使用,但这看起来很丑。 - 在#2中,
full_join()
将通过一条消息“由XXX列加入”。避免这种情况的唯一方法是提供列名by=c('a','b','c')
的显式字符向量。但是为此,我再次需要一个字符向量。丑陋的解决方法将是intersect(names(df1),names(df2))
或suppressMessages()
。当您确定df1和df2中没有多余的列时,这可能会起作用。另一个相当丑陋的方法是使用names(select(df1,c({{cols1}},{{cols2}}))
。
是否有更优雅的方法将cols1
和cols2
转换为字符向量?
解决方法
也许我误解了您的问题,但是在tidyselect上下文中获取字符向量的方法是使用all_of()
:
across(all_of(cols1))
,
深入研究tidyselect documentation后:
f <- function(d,cols1,cols2) {
<do something useful with d>
cols1_c <- tidyselect::eval_select(rlang::enquo(cols1),d)
cols2_c <- tidyselect::eval_select(rlang::enquo(cols2),d)
unique(names(d)[c(cols1_c,cols2_c)])
}
f(iris,c(Sepal.Length,Species),Petal.Width)
# [1] "Sepal.Length" "Species" "Petal.Width"
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。