1

R 中的stargazer 包非常适合将多个回归模型显示为并排的列——这是许多社会科学学科的标准样式。但是,该包不能很好地与 knitr+pandoc 配合使用,因为它生成的输出为 HTML 或 TeX,而不是 Markdown。

作为一种解决方案,我正在创建一个函数,该函数可以生成类似于使用 stargazer 创建的表格,但将输出保存为一个简单的数据框,然后我可以使用 pacakgeskablepanderknitted 文档进行渲染。对于像broom::tidy.

但是,我不知道如何对模型中显示的系数进行排序。以这三个模型为例。使用 stargazer 显示时,最终的系数阶数为c("wt", "qsec", "hp", "cyl", "gear", "carb", "drat")。所有系数的顺序主要基于第一个模型中的系数 ( wt, qsec, cyl, gear, carb)。当第二个模型作为新列附加时,hp行将插入 afterqsec和 before cyl

lm0 <- lm(hp ~ wt + qsec + cyl + gear + carb, mtcars)
lm1 <- lm(qsec ~ hp + cyl + gear + carb, mtcars)
lm2 <- lm(qsec ~ wt + hp + gear + drat, mtcars)

stargazer(lm0, lm1, lm2, type="text")
====================================================
              (1)           (2)             (3)          
----------------------------------------------------
wt           16.879                       0.827**        
            (12.113)                      (0.383)        
qsec         -8.124                                      
            (6.109)                                      
hp                         -0.005        -0.026***       
                          (0.007)         (0.004)        
cyl         18.210**     -0.811***                       
            (8.785)       (0.280)                        
gear         13.342      -1.597***         -0.232        
            (15.115)      (0.441)         (0.439)        
carb         9.277         0.098                         
            (6.345)       (0.222)                        
drat                                       0.099         
                                          (0.636)        
Constant     49.424      29.181***       19.530***       
           (171.876)      (2.398)         (2.766)        
====================================================
Note:                    *p<0.1; **p<0.05; ***p<0.01

最后,我希望生成一个系数名称的字符向量,然后我可以使用它dplyr::arrange()来正确排序多个模型系数的数据框。

排序似乎遵循这个伪算法:

  1. list_1保存系数名称的第一个列表 ( )
  2. 浏览第二个名称列表。如果element_1oflist_2不匹配element_1of list_1,检查下一个元素list_1直到匹配,然后在匹配之前插入
  3. 如果它与其他任何内容不匹配,element_2则放在list_2后面element_1list_1
  4. 重复list_3, 等等

然而,事实证明,编写简单的 R 代码来生成这个订单比我想象的要困难得多。简单地连接向量中的所有系数名称,然后只保留唯一值不会产生正确的顺序,因为新变量(如hp)只是添加到现有变量名称的末尾而不是插入到中间:

library(tidyverse)
names1 <- names(lm0$coefficients) %>% discard(~ .x == "(Intercept)")
names2 <- names(lm1$coefficients) %>% discard(~ .x == "(Intercept)")
names3 <- names(lm2$coefficients) %>% discard(~ .x == "(Intercept)")

# New variables just appended
unique(c(names1, names2, names3))

# [1] "wt"   "qsec" "cyl"  "gear" "carb" "hp"   "drat"

此外,似乎实现这样的事情的唯一方法是使用大量循环,这感觉非常低效。

那么,最后,如何按模型列表中出现的顺序对系数名称的字符向量进行排序或重新排序,优先考虑列表中第一个模型的顺序?也就是说,最终这是我想要得到的字符向量:c("wt", "qsec", "hp", "cyl", "gear", "carb", "drat")


更新:memisc::mtable(lm0, lm1, lm2)是一个巧妙的替代观星者,它实际上返回一个数据帧(而不仅仅是文本),但它不会以现有的顺序插入新的系数,而是将它们附加到列表中(最后带有hpdrat)。它似乎只是连接所有系数名称并使用它们的唯一值。

===================================================
                     lm0        lm1        lm2     
---------------------------------------------------
  (Intercept)       49.424   29.181***  19.530***  
                  (171.876)  (2.398)    (2.766)    
  wt                16.879               0.827*    
                   (12.113)             (0.383)    
  qsec              -8.124                         
                    (6.109)                        
  cyl               18.210*  -0.811**              
                    (8.785)  (0.280)               
  gear              13.342   -1.597**   -0.232     
                   (15.115)  (0.441)    (0.439)    
  carb               9.277    0.098                
                    (6.345)  (0.222)               
  hp                         -0.005     -0.026***  
                             (0.007)    (0.004)    
  drat                                   0.099     
                                        (0.636)    
---------------------------------------------------
4

1 回答 1

1

回答OP的Q

那么,最后,如何按模型列表中出现的顺序对系数名称的字符向量进行排序或重新排序,优先考虑列表中第一个模型的顺序?

这是一个适用于任意数量模型的单线:

unique(names(unlist(lapply(list(lm0, lm1, lm2), coef))))[-1]
#[1] "wt"   "qsec" "cyl"  "gear" "carb" "hp"   "drat"

请注意,代码隐含假设第一个模型始终具有"(Intercept)"作为第一个系数,该系数通过负索引从结果向量中删除[-1]

如果不能保证,使用起来可能更安全

setdiff(unique(names(unlist(lapply(list(lm0, lm1, lm2), coef)))), "(Intercept)")

"(Intercept)"如果有任何结果向量,则从结果向量中删除,无论其位置如何。其余系数名称将保持其顺序:

#[1] "wt"   "qsec" "cyl"  "gear" "carb" "hp"   "drat"

编辑

目前还不太清楚stargazer实施了哪种逻辑来对系数进行排序。但是,根据帮助页面,stargazer 也以不可见的方式返回相同的输出作为字符向量。此外,该table.layout参数可用于仅返回系数部分。这可用于以与以下相同的顺序提取系数的名称stargazer

sgt <- capture.output(stargazer::stargazer(lm0, lm1, lm2, type="text", table.layout = "t"))
setdiff(stringr::str_extract(sgt, "^\\w*"), c("", "Constant"))
#[1] "wt"   "qsec" "hp"   "cyl"  "gear" "carb" "drat"

作为输出stargazer用途cat()capture.output()保持控制台输出干净(感谢@Andrew 提出此建议)。

中的正则表达式str_extract()返回每个字符串开头的第一个“单词”。结果向量再次使用setdiff().

于 2017-01-23T08:24:33.000 回答