使用一个数据帧中的值作为在另一个数据帧上估计的模型的参数

Posted

技术标签:

【中文标题】使用一个数据帧中的值作为在另一个数据帧上估计的模型的参数【英文标题】:Using values in one dataframe as arguments for model estimated on another dataframe 【发布时间】:2019-04-17 07:18:35 【问题描述】:

我希望在一个数据帧中估计模型,但每个模型的公式都有一些来自另一个数据帧的“移动部分”。例如,假设我希望估计以下模型(我无法发布图片并且找不到输入乳胶方程的方法): mpg = a + b*log(w_1 * drat + w_2 * hp)

其中 w_1 和 w_2 是权重,例如为 0.5 或 1。我使用 expand.grid() 创建权重数据框,然后使用 paste() 或 paste0() 对变量进行 mutate() 公式名称和权重值,然后将其传递给 lm() 函数。

但是,估计的模型只是使用权重数据框第一行中的公式。如果我在估计模型之前使用 group_by() 就可以解决这个问题。

问题是 - 为什么?为什么第一个代码不起作用? group_by() 在这里实现了什么使其成为可能?

library(tidyverse)
cars <- mtcars

w <- seq(from=0.5, to=1, by=0.5)
weights <- as_tibble(expand.grid(w1=w,w2=w))


#Doesn't work - the lm model is fit using the formula from the first row only
weights %>%
  mutate(formula_weights = paste0("mpg~log(",w1,"*drat+",w2,"*hp)")) %>%
  mutate(r2 = summary(lm(data=cars, formula = formula_weights))$r.squared)

#Does work - model is fit using the w1 and w2 values from each row (formula_weights)
weights %>%
  mutate(formula_weights = paste0("mpg~log(",w1,"*drat+",w2,"*hp)")) %>%
  group_by(formula_weights) %>%
  mutate(r2 = summary(lm(data=cars, formula = formula_weights))$r.squared)

没有 group_by() 的输出:

# A tibble: 4 x 4
     w1    w2 formula_weights             r2
  <dbl> <dbl> <chr>                    <dbl>
1   0.5   0.5 mpg~log(0.5*drat+0.5*hp) 0.715
2   1     0.5 mpg~log(1*drat+0.5*hp)   0.715
3   0.5   1   mpg~log(0.5*drat+1*hp)   0.715
4   1     1   mpg~log(1*drat+1*hp)     0.715

group_by() 的输出:

# A tibble: 4 x 4
# Groups:   formula_weights [4]
     w1    w2 formula_weights             r2
  <dbl> <dbl> <chr>                    <dbl>
1   0.5   0.5 mpg~log(0.5*drat+0.5*hp) 0.715
2   1     0.5 mpg~log(1*drat+0.5*hp)   0.709
3   0.5   1   mpg~log(0.5*drat+1*hp)   0.718
4   1     1   mpg~log(1*drat+1*hp)     0.715

【问题讨论】:

【参考方案1】:

我们可以加rowwise

library(dplyr)
weights %>%
  mutate(formula_weights = paste0("mpg~log(",w1,"*drat+",w2,"*hp)")) %>% 
  rowwise() %>%
  mutate(r2 = summary(lm(data=cars, formula = formula_weights))$r.squared)
#Source: local data frame [4 x 4]
#Groups: <by row>

# A tibble: 4 x 4
#     w1    w2 formula_weights             r2
#  <dbl> <dbl> <chr>                    <dbl>
#1   0.5   0.5 mpg~log(0.5*drat+0.5*hp) 0.715
#2   1     0.5 mpg~log(1*drat+0.5*hp)   0.709
#3   0.5   1   mpg~log(0.5*drat+1*hp)   0.718
#4   1     1   mpg~log(1*drat+1*hp)     0.715

或使用map

library(purrr)
weights %>%
     mutate(r2 = map_dbl(paste0("mpg~log(",w1,"*drat+",w2,"*hp)"), ~ 
                    summary(lm(data = cars, formula =  .x))$r.squared))
# A tibble: 4 x 3
#     w1    w2    r2
#   <dbl> <dbl> <dbl>
#1   0.5   0.5 0.715
#2   1     0.5 0.709
#3   0.5   1   0.718
#4   1     1   0.715

【讨论】:

当我试图解决我原来的问题时,我看到 rowwise() 和 group_by() 给出了相同的解决方案。我仍然不明白为什么。例如,当我改变 formula_weights 时 - dplyr“知道”这是按行排列的。那么为什么使用带有 formula=formula_weights 的 lm 需要我明确告诉它 rowwise() 呢? @ArielKarlinsky 这与 mutate 的工作方式有关。通常它适用于向量(例如列)。因此它希望使用向量(其他列)作为输入,并应用向量化的函数(例如逐个元素工作)并返回相同长度的向量。 rowwise 和 group_by 将此计算分成组,以便在每个组中独立执行计算。在每个组中,您仍然需要以矢量化方式工作 - 但如果组的大小为 1(例如按行),那么这并不重要。与基本函数 ave() 比较【参考方案2】:

在你的 mutate 中使用 sapply。 summary/lm 未矢量化

weights %>%
mutate(formula_weights = paste0("mpg~log(",w1,"*drat+",w2,"*hp)")) %>%
mutate(r2 = sapply(formula_weights,
                   function(fw) summary(lm(data=cars, formula =))$r.squared))

【讨论】:

sapply 就像使用map(循环)。

以上是关于使用一个数据帧中的值作为在另一个数据帧上估计的模型的参数的主要内容,如果未能解决你的问题,请参考以下文章

计算 2 个数据帧之间的最小距离并估计一个数据帧中的缺失点位置

如何使用实际数据帧中两列中的值索引另一个数据帧,从而在实际数据框中创建列

将其他数据帧中的值获取到新数据帧的循环中

同一数据帧上的多个总和

提取列值并将其作为 Spark 数据帧中的数组分配给另一列

PYTHON Pandas - 根据其他数据帧中的值对数据帧使用 Pandas 样式