`dplyr::select()`使用tidyselection,但如果列不存在则不会出错

nimxete2  于 2023-03-27  发布在  其他
关注(0)|答案(2)|浏览(133)

我有一个应用于数据框的函数,除了一些列。这些列可以使用tidyselection填充。
例如,考虑以下函数:

rename_upper = function(df, except=NULL){
  except = names(select(df, {{except}}))
  rename_with(df, ~ifelse(.x %in% except, .x, toupper(.x)))
}
rename_upper(iris, except=3:5) %>% names()
#> [1] "SEPAL.LENGTH" "SEPAL.WIDTH"  "Petal.Length" "Petal.Width"  "Species"   
rename_upper(iris, except=starts_with("Pet")) %>% names()  
#> [1] "SEPAL.LENGTH" "SEPAL.WIDTH"  "Petal.Length" "Petal.Width"  "SPECIES"

输出是好的,但是如果except包含df中不存在的列,我不希望它抛出错误。
例如,rename_upper(iris, except=6)抛出错误,因为位置6不存在。
不幸的是,使用any_of()不是一个解决方案,因为它会将except限制为一个字符向量,我不能再使用tidyselection。
我能两全其美吗?

3yhwsihp

3yhwsihp1#

也许可以使用try来查看在selectexcept列执行操作时是否有任何错误?
如果select中出现错误并显示警告消息,则所有列都将重命名为toupper

library(dplyr)

rename_upper = function(df, except=NULL){
  tryerror <- try(select(df, {{except}}), silent = T)
  if (class(tryerror) == "try-error") {
    warning(paste0("Column specified in the except argument not found in dataframe '", deparse(substitute(df)), "'"))
    rename_with(df, .cols = everything(), toupper)
  } else {
    except = names(tryerror)
    rename_with(df, ~ifelse(.x %in% except, .x, toupper(.x)))
  }
}

# with error
rename_upper(iris, except=523) %>% names()
[1] "SEPAL.LENGTH" "SEPAL.WIDTH"  "PETAL.LENGTH" "PETAL.WIDTH" 
[5] "SPECIES"     
Warning message:
In rename_upper(iris, except = 523) :
  Column specified in the except argument not found in dataframe 'iris' 

# run as expected
rename_upper(iris, except=3:5) %>% names()
[1] "SEPAL.LENGTH" "SEPAL.WIDTH"  "Petal.Length" "Petal.Width" 
[5] "Species"
mzillmmw

mzillmmw2#

试试看

rename_upper <- function(df, except=NULL){
  nm1 <- setdiff(names(df), names(select(df, any_of({{except}}))))
 df %>%
    rename_with(~ toupper(.x), all_of(nm1))
  

}
  • 测试
> rename_upper(iris, except=6)  %>%
+     names
[1] "SEPAL.LENGTH" "SEPAL.WIDTH"  "PETAL.LENGTH" "PETAL.WIDTH"  "SPECIES"     
> 
> rename_upper(iris, except=starts_with("Pet"))  %>%
+   names
[1] "SEPAL.LENGTH" "SEPAL.WIDTH"  "Petal.Length" "Petal.Width"  "SPECIES"  

> rename_upper(iris, except=3:5) %>% names
[1] "SEPAL.LENGTH" "SEPAL.WIDTH"  "Petal.Length" "Petal.Width"  "Species"

相关问题