【问题标题】:capturing functions using rlang's enexprs使用 rlang 的 enexprs 捕获函数
【发布时间】:2018-08-12 15:09:11
【问题描述】:

我正在编写一个函数,以便该函数的调用者可以以声明方式编写模式:

myschema <- Schema(
  patientID = character,
  temp = numeric,
  treated = logical,
  reason_treated = factor(levels=c('fever', 'chills', 'nausea'))
)

稍后,我将能够使用此架构中声明的类型来组装数据帧。我认为这项工作的最佳人选是使用rlang 中提供的元编程功能:

Schema = function(...) {
  schematypes = rlang::enexprs(...)

}

但是,大多数examples 都与捕获表达式有关,然后将它们用作函数的参数,而不是函数本身。也就是说,我发现很难捕捉到以下表达式的右侧:

patientID = character

然后可以在以后将其评估为character(myvec),只要我得到myvec。这同样适用于以下情况:

reason_treated = factor(levels=c('fever', 'chills', 'nausea'))

我稍后想将其评估为factor(myvec, levels=c('fever', 'chills', 'nausea'))

谢谢!

【问题讨论】:

    标签: r rlang non-standard-evaluation


    【解决方案1】:

    如果我理解正确,您实际上是在用函数构建模式,并且您希望在这些函数可用时将这些函数应用于某些参数。这属于函数式编程而不是rlang 元编程。

    purrr::map 及其“引擎”as_mapper 已经捕获了您想要的大部分功能。你可以直接用它来定义

    Schema <- function(...) { purrr::map( list(...), purrr::as_mapper ) }
    

    您现在可以按照您的建议使用它来构建新模式(对函数定义进行少量修改):

    myschema <- Schema(
      patientID = as.character,   # Note the correct function name
      temp = as.numeric,          # Ditto
      treated = as.logical,       # Tritto
      reason_treated = ~factor(., levels=c('fever', 'chills', 'nausea'))
    )
    # $patientID
    # function (x, ...) 
    # as.character(x = x, ...)
    # <environment: base>
    #
    # $temp
    # function (x, ...) 
    # as.double(x = x, ...)
    # <environment: base>
    #
    # $treated
    # function (x, ...) 
    # as.logical(x = x, ...)
    # <environment: base>
    # 
    # $reason_treated
    # function (..., .x = ..1, .y = ..2, . = ..1) 
    # factor(., levels = c("fever", "chills", "nausea"))
    # <bytecode: 0x00000000027a2d00>
    

    鉴于您的新架构,可以使用 map 的姊妹函数来注册新患者,该函数将两个列表/向量中的参数对齐:

    register_patient <- function(myvec) { purrr::map2( myschema, myvec, ~.x(.y) ) }
    JohnDoe <- register_patient( c(1234, 100, TRUE, "fever") )    
    # $patientID
    # [1] "1234"
    # 
    # $temp
    # [1] 100
    # 
    # $treated
    # [1] TRUE
    # 
    # $reason_treated
    # [1] fever
    # Levels: fever chills nausea
    

    让我们验证每个元素的类型:

    purrr::map( JohnDoe, class )
    # $patientID
    # [1] "character"
    # 
    # $temp
    # [1] "numeric"
    # 
    # $treated
    # [1] "logical"
    # 
    # $reason_treated
    # [1] "factor"
    

    【讨论】:

      猜你喜欢
      • 2019-12-11
      • 2020-03-09
      • 2021-10-07
      • 1970-01-01
      • 1970-01-01
      • 2020-05-12
      • 2023-01-25
      • 2018-08-18
      • 2019-01-24
      相关资源
      最近更新 更多