【问题标题】:paste formula in function (c constant?)在函数中粘贴公式(c 常数?)
【发布时间】:2022-10-18 05:25:15
【问题描述】:

我正在做一个粘贴公式然后返回feols 结果的函数。但是,一开始我得到了一个c。我该如何解决这个问题?

library(dplyr)
library(fixest)

data(base_did)
base_did = base_did %>% mutate(D = 5*rnorm(1080),
                               x2 = 10*rnorm(1080),
                               rand_wei = abs(rnorm(1080)))

f <- function(data, arg=NULL){
  
  arg = enexpr(arg)
  
  if (length(arg) == 0) {
    formula = "D ~ 1"
  } 
  else {
    formula = paste(arg, collapse = " + ")
    formula = paste("D ~ ", formula, sep = "")
  }
  
  formula = paste(formula, " | id + period", sep = "")
  denom.lm <- feols(as.formula(formula), data = data, 
                    weights = abs(data$rand_wei))
  
  return(denom.lm)
}

f(base_did, arg = c(x1,x2))

#Error in feols(as.formula(formula), data = data, weights = abs(data$rand_wei)) : 
#  Evaluation of the right-hand-side of the formula raises an error: 
#  In NULL: Evaluation of .Primitive("c") returns an object of length 1
#while the data set has 1080 rows.

如果我最后return(formula)。我得到[1] "D ~ c + x1 + x2 | id + period"

但我只需要D ~ x1 + x2 | id + period

【问题讨论】:

    标签: r formula paste


    【解决方案1】:

    也许使您的函数工作的一种选择是通过... 传递参数,这样就不需要c,这会阻止c 添加到您的公式中。要完成这项工作,您还可以在函数内切换到 enexprs

    注意:我稍微调整了您的 reprex 函数以仅返回公式。

    library(dplyr, warn = FALSE)
    library(fixest)
    
    data(base_did)
    
    base_did = base_did %>% mutate(D = 5*rnorm(1080),
                                   x2 = 10*rnorm(1080),
                                   rand_wei = abs(rnorm(1080)))
    
    f <- function(data, ...){
      arg = enexprs(...)
      
      if (length(arg) == 0) {
        formula = "D ~ 1"
      } 
      else {
        formula = paste(arg, collapse = " + ")
        formula = paste("D ~ ", formula, sep = "")
      }
      
      formula = paste(formula, " | id + period", sep = "")
      
      as.formula(formula)
    }
    
    
    f(base_did, x1, x2)
    #> D ~ x1 + x2 | id + period
    #> <environment: 0x7fe8f3567618>
    
    f(base_did)
    #> D ~ 1 | id + period
    #> <environment: 0x7fe8f366f848>
    

    更新可能有更好的方法,但经过一些研究,可能的选择是:

    注意:当通过c 传递多个参数时,enexpr 将返回一个call 对象,该对象的行为类似于列表,其中第一个元素包含函数名称,即c。这就是为什么您将c 添加到您的公式中的原因。

    f <- function(data, arg = NULL) {
      arg <- enexpr(arg)
      
      if (length(arg) == 0) {
        formula <- "D ~ 1"
      } else {
        if (length(arg) > 1) arg <- vapply(as.list(arg[-1]), rlang::as_string, FUN.VALUE = character(1))
        
        formula <- paste(arg, collapse = " + ")
        formula <- paste("D ~ ", formula, sep = "")
      }
    
      formula <- paste(formula, " | id + period", sep = "")
    
      as.formula(formula)
    }
    
    
    f(base_did, c(x1, x2))
    #> D ~ x1 + x2 | id + period
    #> <environment: 0x7fa763431388>
    
    f(base_did, x1)
    #> D ~ x1 | id + period
    #> <environment: 0x7fa763538c40>
    
    f(base_did)
    #> D ~ 1 | id + period
    #> <environment: 0x7fa765e22028>
    

    【讨论】:

    • Ty @stefan 回答你,是否可以不使用... 来做到这一点,因为我想创建一个参数arg1 然后arg2(例如arg1:外生变量;arg2:控制变量) .
    • 我需要的功能应该是f(data, arg1=c(x1,x2), arg2 = c(crt1,crt2)
    • 看我的更新。我想出了一个可能且可行的解决方案,但我确信有一个“更清洁”的解决方案。
    • 太棒了!!!您能否向我解释一下vapply(...) 行和vapply 中的参数是如何工作的。我的last post 使用purrr::map_chr 有什么区别吗?
    • 没有。您也可以使用purrr::map_chrvapplyFUN.VALUE=charcter(1) 只是基本的 R 版本,意味着返回一个字符向量。
    【解决方案2】:

    如果您使用fixest 的内置公式操作工具(请参阅here),您可以极大地简化您的函数。特别是点方括号运算符:

    library(fixest)
    data(base_did)
    n = 1080
    base = within(base_did, {
        D = 5 * rnorm(n)
        x2 = 10 *rnorm(n)
        rand_wei = abs(rnorm(n))
        })
    
    f = function(data, ctrl = "1"){
        feols(D ~ .[ctrl] | id + period,
              data = data, weights = ~abs(rand_wei))
    }
    
    est1 = f(base)
    est2 = f(base, ~x1)           # with a formula
    est3 = f(base, c("x1", "x2")) # with a character vector
    
    etable(est1, est2, est3)
    #>                     est1            est2             est3
    #> Dependent Var.:        D               D                D
    #>                                                          
    #> x1                       0.0816 (0.0619)  0.0791 (0.0618)
    #> x2                                       -0.0157 (0.0186)
    #> Fixed-Effects:  -------- --------------- ----------------
    #> id                   Yes             Yes              Yes
    #> period               Yes             Yes              Yes
    #> _______________ ________ _______________ ________________
    #> S.E. type             --          by: id           by: id
    #> Observations       1,080           1,080            1,080
    #> R2               0.12810         0.13005          0.13094
    #> Within R2             --         0.00224          0.00326
    #> ---
    #> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-05
      • 1970-01-01
      • 2020-07-26
      • 2020-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多