r - 以编程方式构建公式而无需字符串操作

标签 r string

例如,考虑 R 中的基本回归模型:

form1 <- Petal.Length ~ Sepal.Length + Sepal.Width
fit1 <- lm(form1, iris)

(我向在这里发帖的任何植物学家道歉。)

为了添加二次项和交互项,我知道三种方法:

1)老式的方式

一次输入一个术语:
form2 <- . ~ Sepal.Length*Sepal.Width + I(Sepal.Length^2) + I(Sepal.Width^2)
fit2 <- update(fit1, form2)

这不会超出小公式的范围,您无法使用它进行编程。

2)丑陋的方式

字符串操作:
vars <- attr(terms(form1), "term.labels")
squared_terms <- sprintf("I(%s^2)", vars)
inter_terms <- combn(vars, 2, paste, collapse = "*")
form2 <- reformulate(c(inter_terms, squared_terms), ".")

这可以扩展,但它并不是真正可编程的,因为函数本身需要进行硬编码。

3)“后门”

直接操作数据
library(lazyeval)
library(dplyr)

square <- function (v) interp(~ I(v1^2), v1 = as.name(v))
inter <- function(v) interp(~ v1*v2, v1 = as.name(v[1]), v2 = as.name(v[2]))

vars <- attr(terms(form1), "term.labels")
squared_terms <- lapply(vars, square) %>%
  set_names(paste0(vars, " ^2"))
inter_terms <- combn(vars, 2, inter, simplify = FALSE) %>%
  set_names(combn(vars, 2, paste, collapse = " x "))

fit2 <- model.frame(fit1) %>%
  mutate_(.dots = squared_terms) %>%
  mutate_(.dots = inter_terms) %>%
  lm(Petal.Length ~ ., data = .)

这是相当可扩展的,并且可编程为变量命名。但这也有点疯狂,因为它违背了使用 formula 的目的。首先。

我希望我能做什么

我希望我能做这样的事情:
library(lazyeval)
library(dplyr)

square <- function (v) interp(~ I(v1^2), v1 = as.name(v))
inter <- function(v) interp(~ v1*v2, v1 = as.name(v[1]), v2 = as.name(v[2]))

squared_terms <- apply.formula(form1, squared_terms)
inter_terms <- combn.formula(form1, 2, inter)

fit2 <- form1 %>%
  append.formula(squared_terms) %>%
  append.formula(inter_terms) %>%
  update(fit1, .)

滥用 dplyr除此之外,这里有两个杀手级功能:
  • 从基本 R 对象中以编程方式生成任意公式项的能力
  • 将项添加到公式中的能力,其行为类似于手动输入的项

  • 特征1可以通过方法3获得,特征2可以通过方法2获得。是否有方法4--中道 ——同时获得?

    最佳答案

    好的,这里有很多动人的部分,但这里有一些非常具体的帮助函数

    extract_rhs_symbols <- function(x) {
        as.list(attr(delete.response(terms(x)), "variables"))[-1]
    }
    symbols_to_formula <- function(x) {
        as.call(list(quote(`~`), x))    
    }
    sum_symbols <- function(...) {
        Reduce(function(a,b) bquote(.(a)+.(b)), do.call(`c`, list(...), quote=T))
    }
    square_terms <- function(x) {
        symbols_to_formula(sum_symbols(sapply(extract_rhs_symbols(x), function(x) bquote(I(.(x)^2)))))
    }
    interact_rhs<-function(x) {
        x[[length(as.list(x))]] <- bquote((.(x[[length(as.list(x))]]))^2)
        x
    }
    add_rhs_dot <- function(x) {
       x[[length(as.list(x))]] <- sum_symbols(quote(.), x[[length(as.list(x))]])    
       x
    }
    add_terms<-function(f, x) {
        update(f, add_rhs_dot(x))
    }
    

    所有这些基本上都将公式作为调用进行操作。

    所以如果你有一个像这样的公式
    my.formula <- Petal.Length ~ Sepal.Length + Sepal.Width + Other
    

    您可以添加平方项
    add_terms(my.formula, square_terms(my.formula))
    

    你可以得到所有的右手互动
    interact_rhs(my.formula)
    

    或者两者都做
    add_terms(interact_rhs(my.formula), square_terms(my.formula))
    

    这使
    Petal.Length ~ Sepal.Length + Sepal.Width + Other + I(Sepal.Length^2) + 
        I(Sepal.Width^2) + I(Other^2) + Sepal.Length:Sepal.Width + 
        Sepal.Length:Other + Sepal.Width:Other
    

    我还没有彻底测试过这个,所以可能会出现这种情况,但它应该在大多数简单的情况下工作。

    关于r - 以编程方式构建公式而无需字符串操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29690068/

    相关文章:

    r - Base R Bar Plot x 轴偏斜

    r - R Shiny 应用程序的本地版本和shinyapps.io 版本之间的颜色不同

    java - 分割用户模式匹配器

    c# - C#中的 bool 变量和字符串值比较

    r - 从R中的字符中提取持续时间

    r - 更改 ggplot2 中特定刻度的颜色

    使用变量标识符从 R 中的 excel 中读取数据

    java - 从字符串中删除所有出现的\

    java - 正则表达式从路径获取带或不带扩展名的文件名

    c - 在c中如何将字符串转换为 double 值?