从数据框中提取公式中的变量

13

我有一个公式,其中包含一些项和一个数据框(早期model.frame()调用的输出),该数据框包含所有这些术语以及更多。 我想要仅包含出现在公式中的变量的模型框架的子集。

ff <- log(Reaction) ~ log(1+Days) + x + y
fr <- data.frame(`log(Reaction)`=1:4,
                 `log(1+Days)`=1:4,
                 x=1:4,
                 y=1:4,
                 z=1:4,
                 check.names=FALSE)

期望的结果是减去 z 列的 frfr[,1:4] 是欺骗行为——我需要一个编程解决方案...)

以下策略不起作用:

fr[all.vars(ff)]
## Error in `[.data.frame`(fr, all.vars(ff)) : undefined columns selected

(因为all.vars()得到的是"Reaction",而不是log("Reaction")

stripwhite <- function(x) gsub("(^ +| +$)","",x)
vars <- stripwhite(unlist(strsplit(as.character(ff)[-1],"\\+")))
fr[vars]
## Error in `[.data.frame`(fr, vars) : undefined columns selected

(因为在+上分割会错误地分割log(1+Days)这个术语)。

我一直在考虑遍历该公式的解析树:

ff[[3]]       ## log(1 + Days) + x + y
ff[[3]][[1]]  ## `+`
ff[[3]][[2]]  ## log(1 + Days) + x

但我没有构建出一个解决方案,而且似乎我正在陷入一个兔子洞。有什么想法吗?


似乎导致您问题的主要变量是 log(1+Days)。您必须这样调用它吗?还是可以使用其他名称? - Thomas
1
attr(terms.formula(ff), "term.labels")是什么意思? - Roman Luštrik
1
我正在尝试提出一般性的解决方案。因此,任何可能出现在从法定公式生成的model.frame()中的内容都必须处理。这就是问题的一部分。 - Ben Bolker
1
或者使用 rownames(attr(terms.formula(ff), "factors")) 也可以获取到因变量。 - Thomas
1
?formula 列出了 terms.formula。 :) - Roman Luštrik
显示剩余4条评论
2个回答

4
这应该可以工作:
> fr[gsub(" ","",rownames(attr(terms.formula(ff), "factors")))]
  log(Reaction) log(1+Days) x y
1             1           1 1 1
2             2           2 2 2
3             3           3 3 3
4             4           4 4 4

感谢Roman Luštrik指导我找到正确的方向。

编辑:看起来你也可以从“variables”属性中提取它:

fr[gsub(" ","",attr(terms(ff),"variables")[-1])]

编辑2:发现第一个问题涉及到I()offset()
ff <- I(log(Reaction)) ~ I(log(1+Days)) + x + y
fr[gsub(" ","",attr(terms(ff),"variables")[-1])]

但是,这些都可以通过正则表达式很容易地进行纠正。但是,如果你遇到像问题中那样的情况,其中一个变量被调用,例如log(x),并且与类似I(log(y))这样的公式一起用于变量y,这将变得非常混乱。


谢谢。我还需要几分钟才能接受这个。在我的情况下,gsub(...)不是必要的,因为空格不匹配不会出现。我在设置示例时意外引入了它。 - Ben Bolker
@BenBolker 是的,最好对一些其他公式进行测试,以查看其是否普适... - Thomas
1
但是你原来的答案 rownames(attr(terms.formula(ff), "factors"))) 在你的问题上似乎可以正常工作。 - Ben Bolker

0

在我看来,唯一的问题是fr表的第二列名称中缺少空格。请添加空格并按照以下方式拉取列:

ff <- log(Reaction) ~ log(1+Days) + x + y
fr <- data.frame(`log(Reaction)`=1:4,
                 `log(1 + Days)`=1:4,
                 x=1:4,
                 y=1:4,
                 z=1:4,
                 check.names=FALSE)


fr[labels(terms(ff))]

如果你相信这两者之间的唯一区别始终在于fr中的名称带有空格,而ff中的名称没有,则以上解决方案是正确的。然而我更喜欢labels(terms(x)),因为它似乎更抽象一些。

fr[gsub(pattern = ' ', replacement = '', x = labels(terms(ff)))]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接