如何按模型列表

时间:2017-01-23 06:37:47

标签: r sorting stargazer tidyverse

R中的stargazer package非常适合将多个回归模型显示为并排列 - 许多社会科学学科的标准样式。但是,该程序包与knitr + pandoc不能很好地兼容,因为它可以生成HTML或TeX输出,但不能生成Markdown。

作为一个解决方案,我创建了一个可以生成类似于用stargazer创建的表的函数,但是将输出保存为一个简单的数据框,然后我可以使用像kable这样的pacak来渲染和pander在针织文件中。使用broom::tidy等函数执行此操作非常简单。

但是,我对如何订购模型中显示的系数感到困惑。以这三种模型为例。与stargazer一起显示时,最终系数顺序为c("wt", "qsec", "hp", "cyl", "gear", "carb", "drat")。所有系数的顺序主要基于第一模型中的系数(wtqseccylgearcarb)。当第二个模型作为新列附加时,hp行将在qsec之后和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_1的{​​{1}}与list_2的{​​{1}}不匹配,请检查element_1的下一个元素,直到匹配为止,然后插入比赛前
  3. list_1之后list_1的{​​{1}}如果与element_2
  4. 中的任何其他内容不匹配,请list_2
  5. 重复element_1,依此类推
  6. 然而,编写简单的R代码来生成此顺序已经证明比我想象的更难。简单地连接一个向量中的所有系数名称然后只保留唯一值并不能产生正确的顺序,因为新的变量(如list_1)只是添加到现有变量名的末尾而不是插入在中间:

    list_3

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

    那么,最后,我如何按照模型列表中的出现顺序对系数名称的字符向量进行排序或重新排序,优先考虑列表中第一个模型的顺序?也就是说,最终这是我想得到的字符向量: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" 是实际返回数据框(而不仅仅是文字)的neat alternative to stargazer,但它不会在现有订单中插入新系数,而是将它们附加到列表(最后有c("wt", "qsec", "hp", "cyl", "gear", "carb", "drat")memisc::mtable(lm0, lm1, lm2))。它似乎只是连接所有系数名称并使用它们的唯一值。

    hp

1 个答案:

答案 0 :(得分: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()中的正则表达式会返回第一个&#34;字&#34;在每个字符串的开头。使用setdiff()再次清除结果向量。