将 broom::tidy 映射到 {fixest} 模型的嵌套列表并保留列表元素的名称

Mapping broom::tidy to nested list of {fixest} models and keep name of list element

我想将 broom::tidy() 应用于嵌套在 fixest_multi 对象中的模型,并将每个列表级别的名称提取为数据框列。这是我的意思的一个例子。

library(fixest)
library(tidyverse)
library(broom)

multiple_est <- feols(c(Ozone, Solar.R) ~ Wind + Temp, airquality, fsplit = ~Month)

此命令为每个部门估计两个模型。变种。 (OzoneSolar.R)每个 Month 的子集加上完整样本。生成的对象如下所示:

> names(multiple_est)
[1] "Full sample" "5"           "6"           "7"           "8"           "9" 
> names(multiple_est$`Full sample`)
[1] "Ozone"   "Solar.R"

我现在想要 tidy 每个模型对象,但将 Month / Dep.var. 组合的信息保留为整理数据框中的列。我想要的输出看起来像这样:

我可以从 tidyr 包 运行 map_dfr 得到这个结果:


> map_dfr(multiple_est, tidy, .id ="Month") %>% head(9)
# A tibble: 9 x 6
  Month       term        estimate std.error statistic  p.value
  <chr>       <chr>          <dbl>     <dbl>     <dbl>    <dbl>
1 Full sample (Intercept)   -71.0     23.6      -3.01  3.20e- 3
2 Full sample Wind           -3.06     0.663    -4.61  1.08e- 5
3 Full sample Temp            1.84     0.250     7.36  3.15e-11
4 5           (Intercept)   -76.4     82.0      -0.931 3.53e- 1
5 5           Wind            2.21     2.31      0.958 3.40e- 1
6 5           Temp            3.07     0.878     3.50  6.15e- 4
7 6           (Intercept)   -70.6     46.8      -1.51  1.45e- 1
8 6           Wind           -1.34     1.13     -1.18  2.50e- 1
9 6           Temp            1.64     0.609     2.70  1.29e- 2

但这只整理了每个 Month 的第一个模型,即具有 Ozone 结果的模型。

我想要的输出看起来像这样:

Month       outcome         term        estimate      more columns from tidy
              
Full sample Ozone           (Intercept)   -71.0   
Full sample Ozone           Wind          -3.06   
Full sample Ozone           Temp          1.84    
Full sample Solar.R         (Intercept)   some value  
Full sample Solar.R         Wind          some value  
Full sample Solar.R         Temp          some value  

... rows repeated for each month 5, 6, 7, 8, 9

如何将 tidy 应用于所有模型并添加另一列来指示模型的结果(存储在模型对象的 name 中)?

因此,随着我深入研究,fixest_mult 有一个非常奇怪的设置。正如您所注意到的,跨越它进行映射或使用 apply 只会访问部分数据帧。事实上,它不仅仅是 "Ozone" 的数据帧,而实际上只是前 6 个数据帧的数据帧(c("Full sample", "5", "6").

的数据帧)

如果您转换为列表,它会访问 data 属性,该属性是所有 12 个数据帧的顺序列表,但会删除您要查找的相关名称。因此,作为一种解决方法,可以使用 pmap() 和名称(在对象的属性中找到)到 tidy(),然后对所需的列使用 mutate()

library(fixest)
library(tidyverse)
library(broom)

multiple_est <- feols(c(Ozone, Solar.R) ~ Wind + Temp, airquality, fsplit = ~Month)
nms <- attr(multiple_est, "meta")$all_names

pmap_dfr(
  list(
    data = as.list(multiple_est),
    month = rep(nms$sample, each = length(nms$lhs)),
    outcome = rep(nms$lhs, length(nms$sample))
  ),
  ~ tidy(..1) %>%
    mutate(
      Month = ..2,
      outcome = ..3,
      .before = 1
    )
)
#> # A tibble: 36 × 7
#>    Month       outcome term        estimate std.error statistic  p.value
#>    <chr>       <chr>   <chr>          <dbl>     <dbl>     <dbl>    <dbl>
#>  1 Full sample Ozone   (Intercept)   -71.0     23.6      -3.01  3.20e- 3
#>  2 Full sample Ozone   Wind           -3.06     0.663    -4.61  1.08e- 5
#>  3 Full sample Ozone   Temp            1.84     0.250     7.36  3.15e-11
#>  4 Full sample Solar.R (Intercept)   -76.4     82.0      -0.931 3.53e- 1
#>  5 Full sample Solar.R Wind            2.21     2.31      0.958 3.40e- 1
#>  6 Full sample Solar.R Temp            3.07     0.878     3.50  6.15e- 4
#>  7 5           Ozone   (Intercept)   -70.6     46.8      -1.51  1.45e- 1
#>  8 5           Ozone   Wind           -1.34     1.13     -1.18  2.50e- 1
#>  9 5           Ozone   Temp            1.64     0.609     2.70  1.29e- 2
#> 10 5           Solar.R (Intercept)  -284.     262.       -1.08  2.89e- 1
#> # … with 26 more rows