【问题标题】:Coerce arguments to simplest type将参数强制转换为最简单的类型
【发布时间】:2025-12-20 19:25:06
【问题描述】:

当使用包shinyplumber 处理用户输入时,通常需要将字符参数转换为数字或逻辑。

我想自动完成,有什么有效的方法?

预期的(这个或类似的):

convert_args <- ...

fun <- function(a, b, c, d){
  convert_args()
  dplyr::lst(a, b, c , d)
}

fun("na","true","1","foo")
#> $a
#> [1] NA
#> 
#> $b
#> [1] TRUE
#> 
#> $c
#> [1] 1
#> 
#> $d
#> [1] "foo"

【问题讨论】:

  • ?type.convert
  • 啊,这个我忘了。它与@Ronak 的提议略有不同,因为默认情况下它将字符转换为因子,并且不会将小写“true”、“t”或“na”转换为它们的逻辑对应项
  • 如果您使用lapply(x, type.convert, as.is = T, na.strings = c('na', 'NA')),它会将内容保留为字符串并捕获小写的"na",但不会捕获"true""false"

标签: r shiny type-conversion plumber


【解决方案1】:

一种选择是使用readr::parse_guess,顾名思义,它试图猜测字符向量的类型。

convert_args <- function(x) {
  lapply(x, readr::parse_guess)  
}

convert_args(c("NA","true","1","foo"))
#[[1]]
#[1] NA

#[[2]]
#[1] TRUE

#[[3]]
#[1] 1

#[[4]]
#[1] "foo"

当我们有"na" 时,这不能直接工作

readr::parse_guess("na")
#[1] "na"

但正如@Moody_Mudskipper 提到的,它可以通过在parse_guess 中指定na 参数来解决

readr::parse_guess("na", c("na", "NA"))
#[1] NA

【讨论】:

  • 感谢@Ronak,这是我一直在寻找的,要获得确切的预期输出,请参阅我在其他答案中的包装。
  • "na" 默认不会转换为NA,但这可以通过readr::parse_guessna 参数来处理。在这种情况下,例如使用上面的lapply(x, readr::parse_guess, c("na","NA")
【解决方案2】:

感谢@Ronak 的解决方案,我围绕readr::parse_guess 构建了一个包装器,以获得完全预期的输出。

我还添加了一个选项来评估未转换的字符输入,因为它也是一项常见任务。


convert_args <- function(na = c("", "NA"), locale = readr::default_locale(),
                         trim_ws = TRUE, guess_integer = FALSE, eval = FALSE){
  if(!requireNamespace("readr")) 
    stop("convert_args() requires package readr to be installed")
  args <- as.list(eval.parent(quote(match.call())))[-1]
  args <- lapply(args, readr::parse_guess, na, locale, trim_ws, guess_integer)
  if (eval){
    args <- lapply(args, function(arg) {
      if(is.character(arg))
        eval(parse(text = arg, parent.frame(2)))
      else
        arg
    })
  }
  list2env(args, envir = parent.frame())
  invisible(NULL)
}
fun <- function(a, b, c, d){
  convert_args()
  dplyr::lst(a, b, c , d)
}


fun("NA","true","1","head(cars,2)")
#> Loading required namespace: readr
#> $a
#> [1] NA
#> 
#> $b
#> [1] TRUE
#> 
#> $c
#> [1] 1
#> 
#> $d
#> [1] "head(cars,2)"
fun2 <- function(a, b, c, d){
  convert_args(eval = TRUE, na = c("na","NA"))
  dplyr::lst(a, b, c , d)
}

fun2("na","true","1","head(cars,2)")
#> $a
#> [1] NA
#> 
#> $b
#> [1] TRUE
#> 
#> $c
#> [1] 1
#> 
#> $d
#>   speed dist
#> 1     4    2
#> 2     4   10

reprex package (v0.3.0) 于 2019 年 6 月 21 日创建

【讨论】: