8

我有一些类似的东西

y ~ x + z

我想把它改造成

y ~ x_part1 + x_part2 + z

更一般地说,我想要一个函数,它接受一个公式并返回该公式,其中所有匹配“^x$”的术语都替换为“x_part1”和“x_part2”。这是我目前的解决方案,但感觉很笨拙......

my.formula <- fruit ~ apple + banana
var.to.replace <- 'apple'
my.terms <- labels(terms(my.formula))
new.terms <- paste0('(', 
                    paste0(var.to.replace, 
                           c('_part1', '_part2'),
                           collapse = '+'),
                    ')')
new.formula <- reformulate(termlabels = gsub(pattern = var.to.replace,
                                             replacement = new.terms,
                                             x = my.terms),                                 
                           response = my.formula[[2]])

另一个需要注意的是,输入公式可以通过交互来指定。

y ~ b*x + z

应该输出这些(等效)公式之一

y ~ b*(x_part1 + x_part2) + z
y ~ b + (x_part1 + x_part2) + b:(x_part1 + x_part2) + z
y ~ b + x_part1 + x_part2 + b:x_part1 + b:x_part2 + z

MrFlick 提倡使用

替代(y ~ b*x + z, 列表(x=quote(x_part1 + x_part2)))

但是当我将要修改的公式存储在变量中时,如

my.formula <- fruit ~ x + banana

这种方法似乎需要更多的按摩:

substitute(my.formula, list(x=quote(apple_part1 + apple_part2)))
# my.formula

对这种方法的必要改变是:

do.call(what = 'substitute',
        args = list(apple, list(x=quote(x_part1 + x_part2))))

但是当 'x' 和 c('x_part', 'x_part2') 都存储在具有名称的变量中时,我无法弄清楚如何使用这种方法,例如var.to.replacenew.terms以上。

4

5 回答 5

9

您可以为此使用该substitute功能

substitute(y ~ b*x + z, list(x=quote(x_part1 + x_part2)))
# y ~ b * (x_part1 + x_part2) + z

这里我们使用命名列表告诉 Rx用表达式替换变量x_part1 + x_part2

于 2016-08-09T18:06:00.100 回答
3

您可以编写一个递归函数来修改公式的表达式树:

replace_term <- function(f, old, new){
  n <- length(f)
  if(n > 1) {
    for(i in 1:n) f[[i]] <- Recall(f[[i]], old, new)

    return(f)
  }

  if(f == old) new else f
}

您可以使用它来修改例如交互:

> replace_term(y~x*a+z - x, quote(x), quote(x1 + x2))
y ~ (x1 + x2) * a + z - (x1 + x2)
于 2016-08-09T17:22:02.030 回答
3

将公式作为字符串使用怎么样?许多基本 R 模型都lm()接受字符串公式(您可以随时使用formula()其他方式)。在这种情况下,您可以使用类似的东西gsub()

f1 <- "y ~ x + z"
f2 <- "y ~ b*x + z"

gsub("x", "(x_part1 + x_part2)", f1)
#> [1] "y ~ (x_part1 + x_part2) + z"

gsub("x", "(x_part1 + x_part2)", f2)
#> [1] "y ~ b*(x_part1 + x_part2) + z"

例如,对于mtcars数据集,假设我们要将mpg(x)替换为disp + hp(x_part1 + x_part2):

f1 <- "qsec ~ mpg + cyl"
f2 <- "qsec ~ wt*mpg + cyl"

f1 <- gsub("mpg", "(disp + hp)", f1)
f2 <- gsub("mpg", "(disp + hp)", f2)

lm(f1, data = mtcars)
#> 
#> Call:
#> lm(formula = f1, data = mtcars)
#> 
#> Coefficients:
#> (Intercept)         disp           hp          cyl  
#>    22.04376      0.01017     -0.02074     -0.56571

lm(f2, data = mtcars)
#> 
#> Call:
#> lm(formula = f2, data = mtcars)
#> 
#> Coefficients:
#> (Intercept)           wt         disp           hp          cyl  
#>   20.421318     1.554904     0.026837    -0.056141    -0.876182  
#>     wt:disp        wt:hp  
#>   -0.006895     0.011126
于 2016-08-10T21:49:14.227 回答
2

如果你只是想修改主效应,你可以减去 x,并添加两个新变量。

> f <- y ~ x + z
> update(f, .~.-x+x_part1 + x_part2)
y ~ z + x_part1 + x_part2
于 2016-08-09T16:25:31.550 回答
0

根据 的要求rcorty,将 'x' 和 c('x_part', 'x_part2') 分别存储在var.to.replacenew.terms中,并采纳MrFlick的使用建议setNames,我们或许可以执行以下操作:

my.formula <- fruit ~ x + banana
var.to.replace <- "x"
new.terms <-  c('x_part', 'x_part2') 
new.terms1 <- paste(new.terms, collapse="+")
do.call("substitute", list(my.formula, setNames(list(str2lang(new.terms1)), var.to.replace))) 

> fruit ~ x_part + x_part2 + banana

顺便说一句,我发现 Paul Johnson 的考古学(第 2.1 节)具有相关性、教育性和娱乐性。

于 2021-12-23T02:16:51.777 回答