【问题标题】:Using dataframe name as a column in a model table使用数据框名称作为模型表中的列
【发布时间】:2018-05-16 20:53:38
【问题描述】:

我对以下为什么不起作用感到困惑。我正在尝试将数据框/tibble 的名称用作多模型数据框中的列,但不断遇到以下错误。这是一个例子:

library(tidyverse)
library(rlang)

set.seed(666)
df1 <- tibble(
  x = 1:10 + rnorm(10),
  y = seq(20, 38, by=2) + rnorm(10),
  z = 2*x + 3*y
)

df2 <- tibble(
  x = 1:10 + rnorm(10),
  y = seq(20, 38, by=2) + rnorm(10),
  z = 4*x + 5*y
)

results <- tibble(dataset = c('df1','df2'))

请注意以下所有操作:

lm(z ~ x + y, data=df1)
lm(z ~ x + y, data=df2)
lm(z ~ x + y, data=eval(sym('df1')))

但是当我尝试以下操作时:

results <- results %>% mutate(model = lm(z ~ x + y, data = eval(sym(dataset))))

我得到了错误

Error in mutate_impl(.data, dots) : 
  Evaluation error: Only strings can be converted to symbols.

有人能弄清楚如何使这项工作发挥作用吗?

【问题讨论】:

  • 这类事情的首选方法是将df1df2 放在一个数据框中,用一列划分两组,然后明确地逐组拟合模型。
  • 是的,我知道这种方法,但实际上数据框非常大,因此将它们作为单个数据框或作为列表列中的数据框条目进行操作很不方便。跨度>

标签: r purrr tibble rlang tidyeval


【解决方案1】:

我们可以使用map函数,指定lm函数如下。

library(tidyverse)
library(rlang)

results2 <- results %>% 
  mutate(model = map(dataset, ~lm(z ~ x + y, data = eval(sym(.)))))

results2
# # A tibble: 2 x 2
#   dataset model   
#   <chr>   <list>  
# 1 df1     <S3: lm>
# 2 df2     <S3: lm>

results2$model[[1]]
# Call:
#   lm(formula = z ~ x + y, data = eval(sym(.)))
# 
# Coefficients:
# (Intercept)            x            y  
#   6.741e-14    2.000e+00    3.000e+00

results2$model[[2]]
# Call:
#   lm(formula = z ~ x + y, data = eval(sym(.)))
# 
# Coefficients:
# (Intercept)            x            y  
#   9.662e-14    4.000e+00    5.000e+00 

【讨论】:

  • 非常感谢您的帮助。现在我看到了答案,我必须弄清楚为什么答案有效——特别是代码中额外的~ 的含义。有点像《Hitchhiker's Guide》中的“42”。
【解决方案2】:

我建议您绑定所有数据并跳过evalsym 调用的稍微不同的路线。这遵循 R for Data Science 的 "Many Models" 章节。

purrr::lst 创建一个数据框列表,其中这些变量的名称作为列表的名称,bind_rows.id 参数使用这些名称创建一个列,将数据标记为来自 df1df2。嵌套会创建一个列data,它是数据框的列表列。然后您可以构建每个数据集的模型。我使用tilde shortcut notation 来构建匿名函数。

结果:您有一个列model,它是一个模型列表。

library(tidyverse)
library(rlang)

results <- lst(df1, df2) %>%
  bind_rows(.id = "dataset") %>%
  group_by(dataset) %>%
  nest() %>%
  mutate(model = map(data, ~lm(z ~ x + y, data = .)))

results$model[[1]]
#> 
#> Call:
#> lm(formula = z ~ x + y, data = .)
#> 
#> Coefficients:
#> (Intercept)            x            y  
#>   6.741e-14    2.000e+00    3.000e+00

您还有一列嵌套数据。如果你不想要它,你可以放弃它:

select(results, -data)
#> # A tibble: 2 x 2
#>   dataset model 
#>   <chr>   <list>
#> 1 df1     <lm>  
#> 2 df2     <lm>

【讨论】:

    猜你喜欢
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 2018-01-04
    • 2017-04-19
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    • 2020-04-11
    相关资源
    最近更新 更多