如何使用 stargazer 以科学计数法显示系数

How to display coefficients in scientific notation with stargazer

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

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

非常感谢任何建议。

这是一个可重现的例子:

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 对此有简单的支持。 您可以尝试其他替代方案,例如 xtableany of the many options here(我没有全部尝试过)

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

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

library(pander)
pander(m1)

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

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

这里有一个 stargazer table 的例子来演示(无耻地从@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))
}

并使用 gsubfn::gsubfn

将其应用于观星者输出
gsubfn("([0-9.]+)", ~replace_numbers(x), star)

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

使用 中的示例模型 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')

更新 如果你想确保尾随零保留在科学计数法中,那么我们可以使用 sprintf 而不是 prettyNum.

像这样

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) 
  )
}