如何使用stargazer在科学记数法中显示系数

如何使用stargazer在科学记数法中显示系数,r,scientific-notation,stargazer,coefficients,R,Scientific Notation,Stargazer,Coefficients,我想使用stargazer或类似工具在R中的表格中比较不同模型(lm、glm、plm、pglm)的结果。 然而,我找不到一种用科学记数法显示系数的方法。这是一个问题,因为截距相当大(约100万),而其他系数很小(约e-7),这会导致大量无用的零,使表格更难读取 我在这里发现了一个类似的问题:。 但是那里的结果需要重新缩放变量,因为我使用计数数据,所以我不想重新缩放它 我非常感谢您的建议。这里有一个可复制的示例: m1 <- lm(Sepal.Length ~ Petal.Length*Se

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

我在这里发现了一个类似的问题:。 但是那里的结果需要重新缩放变量,因为我使用计数数据,所以我不想重新缩放它


我非常感谢您的建议。

这里有一个可复制的示例:

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  
或者,如果您使用的是
knitr
pandoc
,我非常喜欢
pander
,它已经有了automagic科学符号(注意:这是pandoc输出,看起来像是降价,而不是tex输出,然后您将其编织或pandoc到latex/pdf):


可能值得向包维护人员提出包含此选项的功能请求

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

下面是一个示例stargazer表(无耻地抄袭自@mathematic.coffee):

并使用
gsubfn::gsubfn

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

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

使用来自的示例模型
m1


好的,谢谢。您知道支持pglm型号的软件包吗?我尝试了你发布的列表中的几个,但到目前为止并不幸运。pglm非常具体。甚至你最初的选择
stargazer
也不支持它。我认为您必须自己将其转换为一种好的格式(例如,转换为dataframe,然后使用其中一个将为其生成latex的包)。这个问题有点相关,但不直接适用于这里:我喜欢这个答案,因为它明确说明了如何不转换中等值,而只转换极端值。但是我遇到的一个问题是,回归是随着coef的10^-8而来的,所以我需要输入大量的数字,这样一切都不会变成0。这很好,但是最后的R^2看起来像.0131575939。是否有办法将所有未转换的小数点舍入到最接近的千分之一?Good point@wolfsatthedoor-我对其进行了编辑,以便在中等值上使用
round
,以便您也可以在这些值上指定数字。这和你要找的一样吗?我给你赏金是为了安全,现在让我检查一下,很好的回答。我预测,随着时间的推移,随着学术界转向文件的综合降价,这将是一个更受关注的问题!你能更具体地解释一下scipen=-7的作用吗?出于某种原因,舍入也能起作用,但是像.003这样的数字没有被转换成科学符号对不起,在这个版本中,忘记将
scipen
传递到
PrettyNum
。现在更正。基本上,
scipen
是首选的科学符号与标准符号之间的位数差异。更小的(更负的)值会迫使你更积极地使用科学记数法。尽管@dww和当前的答案也存在问题,但它并不完全允许你使用正确的科学记数法,即X.Ye+(Z)。上面的输出显示了这个问题,你知道我的意思吗?我不太明白。你的意思是你想要的是像
1.5x10$^3$
这样的东西,而不是
1.5e+03
?不,我的意思是,1e+06应该是1.2e+06或任何东西。小数应该是一致的。例如,您不希望8.44e-01和8.4e-01成为下一行。您需要8.44e-01,然后是8.40e-01(如果是这样的话)。(上面的例子)好的,我同意。我用
sprintf
而不是
prettyNum
的版本编辑了另一个答案(有赏金的那一个)。这使得科学记数法中的位数始终相同(保留任何尾随零)。如果需要,同样的更改也可以应用于此版本。
library(pander)
pander(m1)
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 = '')
replace_numbers = function(x, cutoff=4, digits=3, scipen=-7) {
  ifelse(nchar(x) < cutoff, x, prettyNum(as.numeric(x), digits=digits, scientific=scipen))
}
gsubfn("([0-9.]+)", ~replace_numbers(x), star)
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')
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) 
  )
}