解析公式

Parsing a formula

我有以下函数,gigl,我试图在其中捕获 | 左右两侧的变量。目前我的代码只捕获准确命名为 sn 的变量。

我如何概括以下内容以评估任何变量而不考虑名称?

gigl <- function(form,data){

  s <- rlang::f_lhs(f_lhs(form))
  n <- rlang::f_rhs(f_lhs(form))
  s <- eval_tidy(data$s) # don't like that I have to use the same name as inputed. Make more general.
  n <- eval_tidy(data$n) # don't like that I have to use the same name as inputed. Make more general.
  output <- tibble(n,s) %>% data.matrix()
  output
  }

fit <- gigl(s | n ~ 1 , data=df)

这是一些玩具数据

library(tidyverse)
df <- tribble(
  ~n, ~s,
  10, 6,
  8, 7,
  6, 5
)

下面应该像上面一样工作,但目前不工作

df2 <- tribble(
  ~total, ~positive,
  10, 6,
  8, 7,
  6, 5
)

fit <- gigl(total | positive ~ 1 , data=df2)

输出应该是

      total  positive
[1,] 10       6
[2,]  8       7
[3,]  6       5

这是一种方法。但是,有很多方法可以破坏此实现,如果输入公式不完全符合您期望的格式,您需要考虑要做什么。例如,我添加了一个小检查以确保左侧确实有一个 |

library(tidyverse)
library(rlang)

gigl <- function(form, data) {

  # Get the left hand side expression from the formula
  lhs <- f_lhs(form)

  # Check that the lhs actually has a `|`
  stopifnot(is.call(lhs), as_string(lhs[[1]]) == "|")

  # Get the expressions from either side of `|` in a list of length 2
  exprs <- as.list(lhs[-1])

  # Create names from them
  names <- map(exprs, expr_name)

  # Evaluate them to get the values
  values <- map(exprs, eval_tidy, data)

  # Construct the data frame
  df <- invoke(data.frame, set_names(values, names))

  # Return
  data.matrix(df)
}

检查它是否有效:

df2 <- tribble(
  ~total, ~positive,
  10, 6,
  8, 7,
  6, 5
)

gigl(total | positive ~ 1 , data = df2)
#>      total positive
#> [1,]    10        6
#> [2,]     8        7
#> [3,]     6        5

或者您可以使用 !!!select 来获得更简洁的解决方案:

gigl2 <- function(form, data) {
  lhs <- f_lhs(form)

  stopifnot(is.call(lhs))
  stopifnot(as_string(lhs[[1]]) == "|")

  exprs <- as.list(lhs[-1])
  df <- select(data, !!!exprs)

  data.matrix(df)
}

gigl2(total | positive ~ 1 , data = df2)
#>      total positive
#> [1,]    10        6
#> [2,]     8        7
#> [3,]     6        5

reprex package (v0.2.0) 创建于 2018-02-19。