【问题标题】:using reformulate to merge non-standard formula使用重新制定合并非标准公式
【发布时间】:2020-11-20 17:00:10
【问题描述】:

给定:

vars <- c("var1", "var2", "var3", "var4")
mm_exp <- expression(
  f(testm, testmodel = 'test', testgraph = g, truetest1 = TRUE, truetest2 = TRUE), 
  f(testm2, testmodel = 'fg'),
  f(testm3, testmodel = 'fg3')
)

我想使用mm_expvars 的所有组合(combn)生成formulas 以输入模型:

#y ~ var1 + var2 + var3 + var4 + f(testm, testmodel = "test", testgraph = g, truetest1 = TRUE, 
#  truetest2 = TRUE) + f(testm2, testmodel = "fg") + f(testm3, testmodel = 'fg3')

#y ~ var1 + var2 + var3 + f(testm, testmodel = "test", testgraph = g, truetest1 = TRUE, 
#  truetest2 = TRUE) + f(testm2, testmodel = "fg") + f(testm3, testmodel = 'fg3')

#y ~ var1 + var2 + f(testm, testmodel = "test", testgraph = g, truetest1 = TRUE, 
#  truetest2 = TRUE) + f(testm2, testmodel = "fg") + f(testm3, testmodel = 'fg3')

#y ~ var1 + var4 + f(testm, testmodel = "test", testgraph = g, truetest1 = TRUE, 
#  truetest2 = TRUE) + f(testm2, testmodel = "fg") + f(testm3, testmodel = 'fg3')


#etc.....

如果我简化mm_exp,我可以得到类似于我想要使用reformulate 的东西(暂时忽略combn):

mm_exp_simplify <- expression(
  f(testm, testmodel = 'test', testgraph = g), 
  f(testm2, testmodel = 'fg'),
  f(testm3, testmodel = 'fg3')
)
reformulate(c(vars, sapply(mm_exp_simplify, deparse)), "y")
# y ~ var1 + var2 + var3 + var4 + f(testm, testmodel = "test", 
#     testgraph = g) + f(testm2, testmodel = "fg") + f(testm3, 
#     testmodel = "fg3")

但如果我重新添加 truetest1 = TRUE, truetest2 = TRUE 会导致问题:

mm_exp <- expression(
  f(testm, testmodel = 'test', testgraph = g, truetest1 = TRUE, truetest2 = TRUE), 
  f(testm2, testmodel = 'fg'),
  f(testm3, testmodel = 'fg3')
)
reformulate(c(vars, sapply(mm_exp, deparse)), "y")
# Error in reformulate(c(vars, sapply(mm_exp, deparse)), "y") : 
#   'termlabels' must be a character vector of length at least one

我也尝试过使用quote,但遇到了类似的问题:

mm_quote <- quote(
  f(testm, testmodel = 'test', testgraph = g, truetest1 = TRUE, truetest2 = TRUE) + 
    f(testm2, testmodel = 'fg') + f(testm3, testmodel = 'fg3')
)
as.formula(paste0("y ~ ", paste(paste(vars, collapse = "+"), deparse(mm_quote), sep = "+")))
# Error in parse(text = x, keep.source = FALSE) : 
#   <text>:2:39: unexpected '='
# 1: y ~ var1+var2+var3+var4+f(testm, testmodel = "test", testgraph = g, truetest1 = TRUE, 
# 2: y ~ var1+var2+var3+var4+    truetest2 =
#                                          ^

有人对如何包含truetest1 = TRUE, truetest2 = TRUE 以及如何获取combn 版本的公式有建议吗?

谢谢

【问题讨论】:

    标签: r string formula eval paste


    【解决方案1】:

    解决方案

    要解决第一个问题,您需要使用deparse1 而不是deparse。像这样:

    reformulate(c(vars, sapply(mm_exp, deparse1)), "y")
    #> y ~ var1 + var2 + var3 + var4 + f(testm, testmodel = "test", 
    #>     testgraph = g, truetest1 = TRUE, truetest2 = TRUE) + f(testm2, 
    #>     testmodel = "fg") + f(testm3, testmodel = "fg3")
    

    关于您的第二个问题,首先您可以创建所有可能长度的所有组合,然后您可以通过这种方式创建所有公式的列表:

    # all vars combinations 
    vars_comb <- lapply(seq_along(vars), function(n) combn(vars, n, simplify = FALSE))
    vars_comb <- unlist(vars_comb, recursive = FALSE)
    
    # all formulas
    lapply(vars_comb, function(v) reformulate(c(v, sapply(mm_exp, deparse1)), "y"))
    

    为什么

    其背后的原因与参数width.cutoff的默认值有关,即deparse中的width.cutoff = 60Ldeparse1中的width.cutoff = 500L

    看看这个:

    # output with deparse
    deparse(expression(f(testm, testmodel = 'test', testgraph = g, truetest1 = TRUE, truetest2 = TRUE)))
    #> [1] "expression(f(testm, testmodel = \"test\", testgraph = g, truetest1 = TRUE, "
    #> [2] "    truetest2 = TRUE))"
    
    # output with deparse and width.cutoff forced to 500
    deparse(expression(f(testm, testmodel = 'test', testgraph = g, truetest1 = TRUE, truetest2 = TRUE)), 
            width.cutoff = 500)
    #> [1] "expression(f(testm, testmodel = \"test\", testgraph = g, truetest1 = TRUE, truetest2 = TRUE))"
    
    # output with deparse1
    deparse1(expression(f(testm, testmodel = 'test', testgraph = g, truetest1 = TRUE, truetest2 = TRUE)))
    #> [1] "expression(f(testm, testmodel = \"test\", testgraph = g, truetest1 = TRUE, truetest2 = TRUE))"
    

    第一个 deparse 创建一个长度为 2 的向量,该向量会干扰 reformulate,因为它创建了公式中不属于投诉的组件。


    对于 R

    如果您像 cmets 中所说的那样拥有 R 3.6,则 deparse1 不可用。 因此,您需要在deparse 中设置width.cutoff = 500L

    解决方案将如下所示:

    # first issue
    reformulate(c(vars, sapply(mm_exp, deparse, width.cutoff = 500L)), "y")
    
    # second issue
    vars_comb <- lapply(seq_along(vars), function(n) combn(vars, n, simplify = FALSE))
    vars_comb <- unlist(vars_comb, recursive = FALSE)
    lapply(vars_comb, function(v) reformulate(c(v, sapply(mm_exp, deparse, width.cutoff = 500L)), "y"))
    

    【讨论】:

    • 哦,我明白了,你需要一些+ 作为分隔符吗?好的等等...
    • 这是您要找的吗?
    • 这是一个很好的答案,谢谢!我之前没见过deparse1,但我在 R 4.0 中看到了它的新特性。如果我想使用旧版本 (R 3.6) 执行此操作,我可以使用 reformulate(c(vars, sapply(mm_exp, deparse(width.cutoff = 500L))), "y") - 它不起作用吗?
    • 不,你应该这样写:reformulate(c(vars, sapply(mm_exp, deparse, width.cutoff = 500L)), "y")
    猜你喜欢
    • 1970-01-01
    • 2013-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-24
    • 1970-01-01
    • 2011-11-28
    • 1970-01-01
    相关资源
    最近更新 更多