12

我想使用 stargazer 或类似工具比较R表中不同模型(lm、glm、plm、pglm)的结果。但是我找不到以科学计数法显示系数的方法。这是一个问题,因为截距相当大(大约一百万),而其他系数很小(大约 e-7),这会导致大量无用的零,从而使表格更难阅读。

我在这里发现了一个类似的问题:Format model display in texreg or stargazer R as science。但是那里的结果需要重新调整变量,因为我使用计数数据,所以我不想重新调整它。

我很感激任何建议。

4

3 回答 3

5

这是一个可重现的示例:

m1 <- lm(Sepal.Length ~ Petal.Length*Sepal.Width,
         transform(iris, Sepal.Length = Sepal.Length+1e6,
                   Petal.Length=Petal.Length*10, Sepal.Width=Sepal.Width*100))
# Coefficients:
#              (Intercept)              Petal.Length               Sepal.Width  Petal.Length:Sepal.Width  
#                1.000e+06                 7.185e-02                 8.500e-03                -7.701e-05  

我不相信stargazer对此有简单的支持。您可以尝试其他替代方案,例如这里xtable许多选项(我没有全部尝试过)

library(xtable)
xtable(m1, display=rep('g', 5)) # or there's `digits` too; see `?xtable`

或者,如果您正在使用knitr或者pandoc我非常喜欢pander,它已经具有自动科学记数法(注意:这是 pandoc 输出,看起来像 markdown,而不是 tex 输出,然后您将其编织或 pandoc 到 latex/pdf):

library(pander)
pander(m1)
于 2015-07-22T05:08:17.687 回答
4

可能值得向包维护者提出功能请求以包含此选项。

同时,您可以用科学记数法自动替换输出中的数字。替换数字时需要注意一些事项。重要的是不要重新格式化作为乳胶编码一部分的数字。此外,请注意不要替换作为变量名一部分的字符。例如,.inSepal.Width很容易被正则表达式误认为是数字。以下代码应处理最常见的情况。但是,例如,如果有人调用他们的变量X_123456789,它可能会X_1.23e+09根据 scipen 设置将其重命名为。所以需要一些谨慎,并且可能需要在 stargazer 包中实施更强大的解决方案。

这是一个示例观星表来演示(无耻地从@mathematical.coffee 复制):

library(stargazer)
library(gsubfn)
m1 <- lm(Sepal.Length ~ Petal.Length*Sepal.Width,
  transform(iris, Sepal.Length = Sepal.Length+1e6,
    Petal.Length=Petal.Length*10, Sepal.Width=Sepal.Width*100))    
star = stargazer(m1, header = F, digit.separator = '')

现在是一个帮助函数来重新格式化数字。您可以使用 digits 和 scipen 参数来控制输出格式。如果您想更频繁地强制使用科学格式,请使用更小(更负面)的 scipen。否则,我们可以通过使用较大的scipen. 该cutoff参数用于防止重新格式化仅由几个字符表示的数字。

replace_numbers = function(x, cutoff=4, digits=3, scipen=-7) {
  ifelse(nchar(x) < cutoff, x, prettyNum(as.numeric(x), digits=digits, scientific=scipen))
}

并将其应用于 stargazer 输出使用gsubfn::gsubfn

gsubfn("([0-9.]+)", ~replace_numbers(x), star)

在此处输入图像描述

于 2019-07-04T17:18:45.950 回答
4

使用 stargazer 获取科学记数法的另一种可靠方法是破解digit.separator参数。此选项允许用户指定分隔小数的字符(.在大多数语言环境中通常是句点)。我们可以篡夺这个参数,将一个唯一可识别的字符串插入到我们希望能够使用正则表达式找到的任何数字中。以这种方式搜索数字的优点是我们只能找到与 stargazer 输出中的数值相对应的数字。即,不可能同时匹配作为变量名一部分的数字(例如 X_12345)或作为乳胶格式化代码的一部分(例如\hline \\[-1.8ex])。在下面我使用字符串::::,但是我们在表中其他地方找不到的任何唯一字符串(例如哈希)都可以。最好避免在标识符标记中包含任何特殊的正则表达式字符,因为这会使事情稍微复杂化。

m1使用其他答案中的示例模型。

mark  = '::::'
star = stargazer(m1, header = F, decimal.mark  = mark, digit.separator = '')

replace_numbers = function(x, low=0.01, high=1e3, digits = 3, scipen=-7, ...) {
  x = gsub(mark,'.',x)
  x.num = as.numeric(x)
  ifelse(
    (x.num >= low) & (x.num < high), 
    round(x.num, digits = digits), 
    prettyNum(x.num, digits=digits, scientific = scipen, ...)
  )
}    

reg = paste0("([0-9.\\-]+", mark, "[0-9.\\-]+)")
cat(gsubfn(reg, ~replace_numbers(x), star), sep='\n')

在此处输入图像描述

更新 如果要确保在科学记数法中保留尾随零,那么我们可以使用sprintfprettyNum 来代替。

像这样

replace_numbers = function(x, low=0.01, high=1e3, digits = 3) {
  x = gsub(mark,'.',x)
  x.num = as.numeric(x)
  form = paste0('%.', digits, 'e')
  ifelse(
    (abs(x.num) >= low) & (abs(x.num) < high), 
    round(x.num, digits = digits), 
    sprintf(form, x.num) 
  )
}

在此处输入图像描述

于 2019-07-07T17:13:58.560 回答