【问题标题】:How can I print a certain number of decimals/digits in R when scipen and digits don't work?当 scipen 和 digits 不起作用时,如何在 R 中打印一定数量的小数/数字?
【发布时间】:2020-12-17 13:39:21
【问题描述】:

我无法让 summary(lm(model) 以科学计数法打印不是 1) 或 b) 有太多小数的数字。

在此问题作为重复问题关闭之前,我已经尝试过此处回答的类似问题中的 scripen() 和 option(digits = x):

我的代码

library(haven)
auto <- haven::read_dta(file = "http://www.stata-press.com/data/r16/auto.dta", .name_repair = "unique")
# Use scale() to create standardised variables
model1_s <- lm(data = auto,
           formula = scale(price) ~ scale(mpg))

我希望看到输出显示只有 3 位小数,而不是科学计数法,如下所示:

summary(model1_s)
# Output truncated.    
>Coefficients:
>            Estimate Std. Error t value Pr(>|t|)    
>(Intercept)  0.000   0.103      0.0        1    
>scale(mpg)  -0.469   0.104     -4.5      0.000 ***

相反,我只能管理:

# Default
summary(model1_s)
>              Estimate Std. Error t value Pr(>|t|)    
>(Intercept) -8.613e-17  1.034e-01   0.000        1    
>scale(mpg)  -4.686e-01  1.041e-01  -4.501 2.55e-05 ***

# Changing options
options(digits = 3)
summary(model1_s)
>             Estimate Std. Error t value Pr(>|t|)    
>(Intercept) -8.61e-17   1.03e-01     0.0        1    
>scale(mpg)  -4.69e-01   1.04e-01    -4.5  2.5e-05 ***

# Using print and digits = x 
print(summary(model1_s), digits = 1)
summary(model1_s)
>            Estimate Std. Error t value Pr(>|t|)    
>(Intercept)   -9e-17      1e-01       0        1    
>scale(mpg)    -5e-01      1e-01      -4    3e-05 ***

# Using scipen
options(scipen = 100, digits = 3)
summary(model1_s)
>                          Estimate             Std. Error t value Pr(>|t|)    
>(Intercept) -0.0000000000000000861  0.1034052818198464840     0.0        1    
>scale(mpg)  -0.4685966881951871832  0.1041111281150861323    -4.5 0.000025 ***

关于我可以做什么的任何提示?

【问题讨论】:

  • 澄清一下,我认为您真正想要的不是打印多个数字,而是四舍五入(对不起,迂腐,但它与方法有所不同)。其次,你真的需要summary 的完整输出吗?如果你只想要系数,那很容易:round(coef(summary(model1_s)), 3)
  • 感谢您的澄清,您说得对,四舍五入是我的问题。像你展示的那样使用 round(coef ...) 是一个很好的解决方法,但我真的很想显示整个摘要。我想我可以做model1_s$coefficients &lt;- round(model1_s$coefficients, 3) summary(model1_s) 这让我很接近。但是有没有我可以应用到摘要或打印以更简单的方法的选项?

标签: r


【解决方案1】:

@RaphaelS 建议的演示(我正在同时处理 :-),

mdl <- lm(mpg~disp+gear,data=mtcars)

summary(mdl)$coefficients
#               Estimate Std. Error   t value    Pr(>|t|)
# (Intercept) 29.1049423 4.48591900  6.488067 4.21414e-07
# disp        -0.0408473 0.00576243 -7.088556 8.46528e-08
# gear         0.1112022 0.96799225  0.114879 9.09333e-01

round(summary(mdl)$coefficients, 3)
#             Estimate Std. Error t value Pr(>|t|)
# (Intercept)   29.105      4.486   6.488    0.000
# disp          -0.041      0.006  -7.089    0.000
# gear           0.111      0.968   0.115    0.909

另外,我认为 R 中没有任何内容可以以这种方式打印它。您可以选择重写(抄袭!)printCoefmat(用于print.summary.lm 等)以说明您的偏好。一种这样的尝试:

printCoefmat_round <- 
  function (x, digits = max(3L, getOption("digits") - 2L), signif.stars = getOption("show.signif.stars"), 
            signif.legend = signif.stars, dig.tst = max(1L, min(5L, digits - 1L)),
            cs.ind = 1:k, tst.ind = k + 1, zap.ind = integer(), P.values = NULL,
            has.Pvalue = nc >= 4L && length(cn <- colnames(x)) && substr(cn[nc], 1L, 3L) %in% c("Pr(", "p-v"),
            eps.Pvalue = .Machine$double.eps, na.print = "NA", quote = FALSE, right = TRUE, ...,
            n = NA) {
    if (is.null(d <- dim(x)) || length(d) != 2L) 
      stop("'x' must be coefficient matrix/data frame")
    nc <- d[2L]
    if (is.null(P.values)) {
      scp <- getOption("show.coef.Pvalues")
      if (!is.logical(scp) || is.na(scp)) {
        warning("option \"show.coef.Pvalues\" is invalid: assuming TRUE")
        scp <- TRUE
      }
      P.values <- has.Pvalue && scp
    }
    else if (P.values && !has.Pvalue) 
      stop("'P.values' is TRUE, but 'has.Pvalue' is not")
    if (has.Pvalue && !P.values) {
      d <- dim(xm <- data.matrix(x[, -nc, drop = FALSE]))
      nc <- nc - 1
      has.Pvalue <- FALSE
    }
    else xm <- data.matrix(x)
    k <- nc - has.Pvalue - (if (missing(tst.ind)) 
      1
      else length(tst.ind))
    if (!missing(cs.ind) && length(cs.ind) > k) 
      stop("wrong k / cs.ind")
    Cf <- array("", dim = d, dimnames = dimnames(xm))
    ok <- !(ina <- is.na(xm))
    for (i in zap.ind) xm[, i] <- zapsmall(xm[, i], digits)
    if (length(cs.ind)) {
      acs <- abs(coef.se <- xm[, cs.ind, drop = FALSE])
      if (any(ia <- is.finite(acs))) {
        digmin <- 1 + if (length(acs <- acs[ia & acs != 0])) 
                        floor(log10(range(acs[acs != 0], finite = TRUE))) else 0
        Cf[, cs.ind] <- format(round(coef.se, if (is.na(n)) max(1L, digits - digmin) else n), digits = digits)
      }
    }
    if (length(tst.ind)) 
      Cf[, tst.ind] <- format(round(xm[, tst.ind], digits = if (is.na(n)) dig.tst else min(dig.tst, n)), 
                              digits = digits)
    if (any(r.ind <- !((1L:nc) %in% c(cs.ind, tst.ind, if (has.Pvalue) nc)))) 
      for (i in which(r.ind)) Cf[, i] <- format(xm[, i], digits = digits)
    ok[, tst.ind] <- FALSE
    okP <- if (has.Pvalue) ok[, -nc] else ok
    x1 <- Cf[okP]
    dec <- getOption("OutDec")
    if (dec != ".") x1 <- chartr(dec, ".", x1)
    x0 <- (xm[okP] == 0) != (as.numeric(x1) == 0)
    if (length(not.both.0 <- which(x0 & !is.na(x0)))) {
      Cf[okP][not.both.0] <- format(xm[okP][not.both.0], digits = if (is.na(n)) max(1L, digits - 1L) else n)
    }
    if (any(ina)) Cf[ina] <- na.print
    if (P.values) {
      if (!is.logical(signif.stars) || is.na(signif.stars)) {
        warning("option \"show.signif.stars\" is invalid: assuming TRUE")
        signif.stars <- TRUE
      }
      if (any(okP <- ok[, nc])) {
        pv <- as.vector(xm[, nc])
        Cf[okP, nc] <-
          if (is.na(n)) {
            format.pval(pv[okP], digits = dig.tst, eps = eps.Pvalue)
          } else format(round(pv[okP], digits = n), digits = n)
        signif.stars <- signif.stars && any(pv[okP] < 0.1)
        if (signif.stars) {
          Signif <- symnum(pv, corr = FALSE, na = FALSE, 
                           cutpoints = c(0, 0.001, 0.01, 0.05, 0.1, 1), 
                           symbols = c("***", "**", "*", ".", " "))
          Cf <- cbind(Cf, format(Signif))
        }
      } else signif.stars <- FALSE
    } else signif.stars <- FALSE
    print.default(Cf, quote = quote, right = right, na.print = na.print, ...)
    if (signif.stars && signif.legend) {
      if ((w <- getOption("width")) < nchar(sleg <- attr(Signif, 
                                                         "legend"))) 
        sleg <- strwrap(sleg, width = w - 2, prefix = "  ")
      cat("---\nSignif. codes:  ", sleg, sep = "", fill = w + 
                                                     4 + max(nchar(sleg, "bytes") - nchar(sleg)))
    }
    invisible(x)
  }

演示,使用上面的mdl

printCoefmat_round(summary(mdl)$coefficients, n=3)
#             Estimate Std. Error t value Pr(>|t|)    
# (Intercept)   29.105      4.486   6.488    0.000 ***
# disp          -0.041      0.006  -7.089    0.000 ***
# gear           0.111      0.968   0.115    0.909    
# ---
# Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

【讨论】:

  • 感谢您的建议!当我写信给@RaphaelS 时,这只会打印系数。我不能在整个摘要中使用它,例如:round(summary(model1_s), 3)。有没有我可以应用于摘要或打印以更简单的方式进行的选项?我在 R 和 Stata 中展示了一些学生示例,在 Stata 中,阅读输出要容易得多。到目前为止,似乎我必须跳过这么多圈才能获得在 Stata 中非常容易获得的相同输出,我担心他们将无法在 R 中遵循它。
  • 我知道你的要求,而且你不是第一个......但我认为没有一个简单的解决方案来获得(a)那种控制数字/scipen, (b) 模型摘要的其余显示组件。您可以重写print.summary.*(它正在使用哪种方法)并尝试在那里强制执行。
  • @HDkarlsen 我认为您实际上应该将此视为 R 的优势,它提供了许多学生应该接受的统计细节,并且大多数包的函数输出具有一致性。跨度>
  • 我明白你的意思,@RaphaelS。谢谢你们的建议:知道我想要实现的目标并不简单,这至少很有帮助。
猜你喜欢
  • 2019-10-08
  • 2017-07-04
  • 2023-03-09
  • 1970-01-01
  • 2014-10-28
  • 1970-01-01
  • 1970-01-01
  • 2021-12-15
  • 2021-03-29
相关资源
最近更新 更多