【问题标题】:Proper method to append to a formula where both formula and stuff to be appended are arguments附加到公式的正确方法,其中公式和要附加的东西都是参数
【发布时间】:2013-02-12 18:53:38
【问题描述】:

我在这里阅读了大量关于 SO 的内容,并了解到我通常应该避免将 formula objects 作为字符串进行操作,但我还没有完全找到如何以安全的方式执行此操作:

tf <- function(formula = NULL, data = NULL, groups = NULL, ...) {
# Arguments are unquoted and in the typical form for lm etc
# Do some plotting with lattice using formula & groups (works, not shown)
# Append 'groups' to 'formula':
# Change y ~ x as passed in argument 'formula' to
# y ~ x * gr where gr is the argument 'groups' with
# scoping so it will be understood by aov
new_formula <- y ~ x * gr
# Now do some anova (could do if formula were right)
model <- aov(formula = new_formula, data = data)
# And print the aov table on the plot (can do)
print(summary(model)) # this will do for testing
}

也许我最接近的是使用reformulate,但这只会在 RHS 上给出+,而不是*。我想使用这样的功能:

p <- tf(carat ~ color, groups = clarity, data = diamonds)

并获得克拉 ~ 颜色 * 净度的 aov 结果。提前致谢。

解决方案

这是一个基于@Aaron 评论的工作版本,它演示了正在发生的事情:

tf <- function(formula = NULL, data = NULL, groups = NULL, ...) {
print(deparse(substitute(groups)))
f <- paste(".~.*", deparse(substitute(groups)))
new_formula <- update.formula(formula, f)
print(new_formula)
model <- aov(formula = new_formula, data = data)
print(summary(model))
}

【问题讨论】:

    标签: r formula


    【解决方案1】:

    我认为 update.formula 可以解决您的问题,但我在函数调用中遇到了更新问题。它将像我在下面编码的那样工作,但请注意,我将列传递给组,而不是变量名。然后将该列添加到函数数据集,然后更新工作。

    我也不知道它是否完全符合您在第二个等式中的要求,但请查看 update.formula 的帮助文件并稍微弄乱一下。

    http://stat.ethz.ch/R-manual/R-devel/library/stats/html/update.formula.html

    tf <- function(formula,groups,d){
      d$groups=groups
      newForm = update(formula,~.*groups)
      mod = lm(newForm,data=d)
    }
    
    dat  = data.frame(carat=rnorm(10,0,1),color=rnorm(10,0,1),color2=rnorm(10,0,1),clarity=rnorm(10,0,1))
    m = tf(carat~color,dat$clarity,d=dat)
    m2 = tf(carat~color+color2,dat$clarity,d=dat)
    
    tf2 <- function(formula, group, d) {
      f <- paste(".~.*", deparse(substitute(group)))
      newForm <- update.formula(formula, f)
      lm(newForm, data=d)
    }
    mA = tf2(carat~color,clarity,d=dat)
    m2A = tf2(carat~color+color2,clarity,d=dat)
    

    编辑: 正如@Aaron 指出的那样,deparsesubstitute 解决了我的问题:我在代码示例中添加了 tf2 作为更好的选择,这样您就可以看到两者是如何工作的。

    【讨论】:

    • 感谢您查看此@slammaster 我想我可能在函数内部遇到了与update.formula 相同的问题!对于调用的 lattice 部分,我必须让 groups 参数是数据框中某些东西的不带引号的名称,所以我不能使用 'dat$clarity',我只能使用 'clarity' 作为参数.因此,lmaov 调用必须在附加组后以相同的方式工作。
    • 尝试更新一个字符串(格式不好,因为在评论中,对不起...): tf
    • @Aaron:应该作为答案发布。
    • @Aaron 请给出答案,以便我接受。你比我更擅长黑魔法!谢谢。布莱恩
    • 也许它应该是一个答案,但感觉就像是对@slammaster 的答案的一个小调整,他提出了基本的想法。也许 slammaster 愿意编辑以包含调整,然后您可以接受这个?
    【解决方案2】:

    当我在函数内定义和调用函数时遇到问题时,我使用的一种技术是将参数作为字符串传递,然后根据这些字符串在函数内构造调用。这就是这里的样子。

    tf <- function(formula, data, groups) {
      f <- paste(".~.*", groups)
      m <- eval(call("aov", update.formula(as.formula(formula), f), data = as.name(data)))
      summary(m)
    }
    
    tf("mpg~vs", "mtcars", "am") 
    

    有关此示例的另一个示例,请参阅我之前的一个问题的答案:https://stackoverflow.com/a/7668846/210673

    另请参阅此问题的姊妹问题的答案,我建议与 xyplot 使用类似的东西:https://stackoverflow.com/a/14858661/210673

    【讨论】:

    • 感谢其他建议和链接。我有我的函数的工作版本,它们使用与您说明的方法类似的方法将带引号的名称作为参数。出于某种原因,我想到要转换为更“官方”或更流畅的公式界面,这导致我陷入了这个泥潭!从长远来看,我会变得更有知识,但这比我开始时想象的要多得多。再次感谢。
    • 我在这里的回答也可能对未来的搜索者有用:stackoverflow.com/a/14940094/210673
    猜你喜欢
    • 2018-06-14
    • 2011-10-20
    • 1970-01-01
    • 2020-05-11
    • 1970-01-01
    • 2020-06-03
    • 2018-07-01
    • 1970-01-01
    • 2020-06-07
    相关资源
    最近更新 更多