【问题标题】:Formatting Decimal places in R格式化R中的小数位
【发布时间】:2011-03-27 12:00:12
【问题描述】:

我有一个数字,例如 1.128347132904321674821,我希望在输出到屏幕(或写入文件)时仅显示两位小数。如何做到这一点?

x <- 1.128347132904321674821

编辑:

用途:

options(digits=2)

已被建议作为可能的答案。有没有办法在脚本中指定它以供一次性使用?当我将它添加到我的脚本中时,它似乎没有做任何不同的事情,而且我对大量重新输入以格式化每个数字不感兴趣(我正在自动化一个非常大的报告)。

--

答案:round(x, digits=2)

【问题讨论】:

  • 如果使用 options(digits=4),那么计算不会限制为 4 位,是吗?在那种情况下,它会使程序的准确性大大降低。它只影响打印时的数字,对吗?
  • controls the number of digits to print when printing numeric values. It is a suggestion only. Valid values are 1...22 with default 7. See the note in print.default about values greater than 15. from ?options 它只影响输出。
  • 请注意round(23, digits=2) 将打印23 而不是23.00。如果你想要后者,试试stackoverflow.com/a/12135122/180892
  • @PaulHurleyuk,我认为在编程中使用尽可能少的库是一种很好的做法。为每个琐碎的需求使用不同库的人通常会导致混乱、大文件、可移植性问题等。

标签: r formatting rounding r-faq


【解决方案1】:

背景:此页面上建议的一些答案(例如,signifoptions(digits=...))不保证显示任意数字的特定小数位数。我认为这是 R 中的一个设计特征,良好的科学实践包括根据“significant figures”的原则显示一定数量的数字。然而,在许多领域(例如,APA style、业务报告)中,格式要求要求显示一定数量的小数位。这样做通常是出于一致性和标准化目的,而不是关注重要数字。

解决方案

以下代码正好显示数字x 的两位小数。

format(round(x, 2), nsmall = 2)

例如:

format(round(1.20, 2), nsmall = 2)
# [1] "1.20"
format(round(1, 2), nsmall = 2)
# [1] "1.00"
format(round(1.1234, 2), nsmall = 2)
# [1] "1.12"

更通用的函数如下,其中x 是数字,k 是要显示的小数位数。 trimws 删除任何前导空格,如果您有数字向量,这可能很有用。

specify_decimal <- function(x, k) trimws(format(round(x, k), nsmall=k))

例如,

specify_decimal(1234, 5)
# [1] "1234.00000"
specify_decimal(0.1234, 5)
# [1] "0.12340"

替代方案的讨论:

formatC answerssprintf answers 运行良好。但在某些情况下,它们会显示负零,这可能是不需要的。即,

formatC(c(-0.001), digits = 2, format = "f")
# [1] "-0.00"
sprintf(-0.001, fmt = '%#.2f')
# [1] "-0.00"

一种可能的解决方法如下:

formatC(as.numeric(as.character(round(-.001, 2))), digits = 2, format = "f")
# [1] "0.00" 

【讨论】:

  • +1 只有对我有用的答案,正确地将0.0001 打印为0.00
  • format()prettyNum() 之类的函数如何将数字转换为字符,这一直困扰着我。你会如何解决这个问题?
  • @JeromyAnglim 我注意到上面的解决方案有一个可能的边缘情况缺点,即固定小数点前的字符数,例如format(c(10, 1), nsmall=1) 产生 "10.0" " 1.0"(注意 1.0 前面的前导空格。而 sprintf() 函数似乎可以保证小数点两边的格式更好,例如 sprintf(c(10,1), fmt = '%#.1f') 摆脱了那个讨厌的前导空格并返回"10.0" "1.0".
  • 前导空格是一种功能,用于在列中使用format 的结果时对齐小数点。
  • @FengJiang 这不是函数的问题。相反,您或许应该避免将数字选项设置得太高。请参阅print.default help 中的警告。它警告说设置位数 >=16 会导致打印问题。
【解决方案2】:

您可以根据需要格式化一个数字,例如x,最多保留小数位。这里x 是一个有很多小数位的数字。假设我们希望显示此数字的小数点后 8 位:

x = 1111111234.6547389758965789345
y = formatC(x, digits = 8, format = "f")
# [1] "1111111234.65473890"

这里format="f" 给出通常小数位的浮点数,比如xxx.xxx,digits 指定位数。相比之下,如果你想获得一个整数来显示你会使用format="d"(很像sprintf)。

【讨论】:

  • 虽然我不清楚 OP 到底在问什么,但从评分最高的答案来看,我不禁注意到 formatC 几乎完全是我用于此目的的。我认为这个答案很好,并且根据 OP 的要求在 base R 中。
  • 你们中的任何人都可以帮助解决这个问题吗? stackoverflow.com/q/53279593/5224236
  • 此答案比所选答案效果更好。 formatC 不受选项(数字)的影响
【解决方案3】:

你可以试试我的包formattable

> # devtools::install_github("renkun-ken/formattable")
> library(formattable)
> x <- formattable(1.128347132904321674821, digits = 2, format = "f")
> x
[1] 1.13

好消息是,x 仍然是一个数字向量,您可以使用相同的格式进行更多计算。

> x + 1
[1] 2.13

更好的是,数字不会丢失,您可以随时重新格式化更多数字:)

> formattable(x, digits = 6, format = "f")
[1] 1.128347

【讨论】:

  • 这样一个小小的刺痛了我一上午。出于某种原因,R 只会对某些列的显示进行四舍五入。我需要这个修复,因为我还必须对这些列执行计算。这行得通。谢谢!
  • 我喜欢 formattable 胜过任何 baseR 函数。最大的优点是将变量保留为数字。
【解决方案4】:

假设您希望保留尾随零,则保留 2 位小数

sprintf(5.5, fmt = '%#.2f')

给了

[1] "5.50"

正如@mpag 下面提到的,似乎 R 有时可以通过 this 和 round 方法给出意想不到的值,例如sprintf(5.5550, fmt='%#.2f') 给出 5.55,而不是 5.56

【讨论】:

  • 然而,虽然 sprintf 舍入,但 sprintf(5.5550, fmt='%#.2f') 给出了一个稍微出乎意料的结果:5.55。 sprintf(5.555000000001, fmt='%#.2f') 给出 5.56。这似乎是 R 中舍入的一般“问题”,因为 round, nsmall 方法给出了相同的结果。
  • 感谢@mpag,我不知道 R 在边界四舍五入方面遇到了困难,我刚刚尝试使用 5.565 进行四舍五入,而 5.545 向下舍入。我想这是他们处理浮点不精确的方式。我认为我没有在其他语言中看到过这种行为,我猜这意味着它们有内置的解决方法
  • 我认为他们故意将这些值视为精确度的限制。他们认为 5.555 的值实际上与 5.5554 的“真实”值 5.5546 产生的可能性一样。但是,如果您继续这种舍入游戏,如果您一次执行一位数,5.444445 可能(未经测试)最终为“6”。但你可能是对的,这可能是二进制表示略低于或高于 5.55 的问题。
  • 是的,我认为如果它是故意的,它也会在 5.565 和 5.545 之间保持一致。 “随机性”向我表明这是一个浮点表示法。
  • 你们中的任何人都可以帮助解决这个问题吗? stackoverflow.com/q/53279593/5224236
【解决方案5】:

如果您更喜欢有效数字而不是固定数字,那么signif 命令可能会很有用:

> signif(1.12345, digits = 3)
[1] 1.12
> signif(12.12345, digits = 3)
[1] 12.1
> signif(12345.12345, digits = 3)
[1] 12300

【讨论】:

  • 谢谢保罗。这两个并不是我想要的,但 signif 引导我找到了 round() 这正是我所需要的。干杯,
  • Error: could not find function "fixed"
  • signif 适用于提供的特定数字,但我认为常见的应用问题是当您需要精确显示两位小数但您不知道该数字是什么提前。在这种情况下,signif 将根据实际数字给出不同的小数位数。
  • fixed 在任何地方都找不到。请修复它,否则应该删除这个误导性的答案。
  • @JeromyAnglim 当我们想要 3sf 时如何解决这个问题?有时它给我 3sf,有时是 4sf,等等。我们如何解决这个问题?
【解决方案6】:

类似的东西:

options(digits=2)

数字选项的定义:

digits: controls the number of digits to print when printing numeric values.

【讨论】:

  • 有没有办法在运行脚本时动态设置?
  • 这适用于在 R 控制台中输出,但在我的脚本中不起作用(它们仍然带有 .1289273982)
  • 我有一个奇怪的行为,digits 选项似乎没有设置小数点后的位数。例如,当我设置选项(数字 = 2)时,打印 7.25 会导致输出 7.2,1234.25 变为 1234,而 0.25 仍为 0.25。是否有其他选项与之交互?
  • 如果您只需要一次使用,绝对不应该这样做。更改选项将影响一切。
【解决方案7】:

检查函数prettyNum、格式

要试用零(例如 123.1240)使用 sprintf(x, fmt='%#.4g')

【讨论】:

  • @42 我提倡学习sprintf,它基本上是一个格式化的框架
  • @jangorecki 我不确定你的意思。我所做的(5 年多前)只是建议进行拼写更正。
  • @42 我觉得你在fmt arg 上抱怨,对不起!
  • 我认为 OP 在固定小数位之后而不是固定数字之后。您的答案中的 g 似乎是固定数字,使用 f 效果更好。
【解决方案8】:

函数formatC() 可用于将数字格式化为两位小数。即使结果值包含尾随零,此函数也会给出两位小数。

【讨论】:

    【解决方案9】:

    我正在使用这个变体来强制打印 K 个小数位:

    # format numeric value to K decimal places
    formatDecimal <- function(x, k) format(round(x, k), trim=T, nsmall=k)
    

    【讨论】:

      【解决方案10】:

      请注意,R 中的数字对象以double precision 存储,这为您提供(大约)16 位十进制数字的精度 - 其余的将是噪音。我承认上面显示的数字可能只是一个示例,但它是 22 位长。

      【讨论】:

      • 已确认,仅供参考。我捣碎了键盘。
      【解决方案11】:

      在我看来是这样的

      library(tutoR)
      format(1.128347132904321674821, 2)
      

      一点点online help

      【讨论】:

      • 我找到了这个,但它需要一个包,我正在寻找基本包中的东西。
      • @brandon,format() 是基础的一部分。打开 R 并输入 ?format ... 不需要任何包。
      • Hrmmm,你看看这个输出什么? [1] "1.128347" 否则,你说它在基础包中是对的,我的错。
      • 也许尝试format.default(x, digits = 2) 只是根据提供的链接在黑暗中拍摄。该信息是我通常阅读的文档中缺少的一些信息,我希望也能看到打印输出。
      • 刚刚注意到您的链接指向 tutoR 文档,这不是基础的一部分。
      【解决方案12】:

      如果您只想对数字或列表进行四舍五入,只需使用

      round(data, 2)
      

      然后,数据将四舍五入到小数点后两位。

      【讨论】:

        【解决方案13】:

        这是我从单位到数百万的方法。 数字参数让我调整有效值的最小数量(整数+小数)。你可以先在里面调整小数舍入。

        number <-function(number){
          result <- if_else(
            abs(number) < 1000000,
            format(
              number, digits = 3,
              big.mark = ".",
              decimal.mark = ","
            ),
            paste0(
              format(
                number/1000000,
                digits = 3,
                drop0trailing = TRUE,
                big.mark = ".",
                decimal.mark = ","
              ),
              "MM"
            )
          )
          # result <- paste0("$", result)
          return(result)
        }
        

        【讨论】:

          【解决方案14】:

          我编写了这个可以改进的函数,但看起来在极端情况下效果很好。例如,在 0.9995 的情况下,投票正确答案给我们 1.00,这是不正确的。在数字没有小数的情况下,我使用该解决方案。

          round_correct <- function(x, digits, chars = TRUE) {
            if(grepl(x = x, pattern = "\\.")) {
              y <- as.character(x)
              pos <- grep(unlist(strsplit(x = y, split = "")), pattern = "\\.", value = FALSE)
              if(chars) {
                return(substr(x = x, start = 1, stop = pos + digits))
              }
              return(
                as.numeric(substr(x = x, start = 1, stop = pos + digits))
              )
            } else {
              return(
                format(round(x, 2), nsmall = 2)
              )
            }
          }
          

          例子:

          round_correct(10.59648, digits = 2)
          [1] "10.59"
          round_correct(0.9995, digits = 2)
          [1] "0.99"
          round_correct(10, digits = 2)
          [1] "10.00"
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-06-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-04
            相关资源
            最近更新 更多