在R中格式化小数位数

365

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

x <- 1.128347132904321674821

编辑:

使用:

options(digits=2)
已经被建议作为可能的答案。是否有一种方法可以在脚本中指定它以供一次性使用?当我将其添加到我的脚本中时,它似乎没有任何不同的操作,并且我不想重新键入大量格式化每个数字(我正在自动化一个非常大的报告)。
--
回答:round(x,digits = 2)

2
相关问题:https://dev59.com/p3E95IYBdhLWcg3wf98F控制R语言中的数字。 - Shane
如果使用options(digits = 4),那么并不会将计算限制在4位数字内,是吗?如果是这样的话,程序的准确度会大大降低。它仅影响到在打印出数字时的显示格式,对吗? - MikeZ
当打印数字时,此选项控制要打印的数字位数。它仅是一个建议。有效值为1...22,默认为7。请参阅print.default中有关大于15的值的注释。它只影响输出。 - Brandon Bertelsen
2
请注意,round(23, digits=2)将打印23而不是23.00。如果您想要后者,请尝试https://dev59.com/C3A75IYBdhLWcg3wJFqY#12135122。 - Jeromy Anglim
8
@PaulHurleyuk,我认为在编程中尽可能使用最少量的库是一个好的实践。那些为每个琐碎需求使用不同库的人通常最终会产生混乱、大文件、可移植性问题等。 - Rodrigo
https://dev59.com/1mXWa4cB1Zd3GeqPNHiW - M--
15个回答

523
背景:在这个页面上提供的一些答案(例如signifoptions(digits=...))并不保证以任意数字为基础来显示一定数量的小数位。我认为这是 R 的设计特性,其中遵循科学实践原则需要显示一定数量的数字,这基于“有效数字”的原则。然而,在许多领域中(如APA 样式,商业报告),格式要求指定显示一定数量的小数位。通常这样做是为了保持一致性和标准化而不是关注有效数字。

解决方案:

以下代码为数字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))

E.g.,

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

备选方案讨论:

formatC答案sprintf答案都能够较好地解决问题。但在某些情况下,它们会显示不必要的负零。也就是说:

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" 

11
唯一对我有用的答案,正确地将“0.0001”打印为“0.00”。 - ThomasH
19
format()prettyNum() 这样的函数将数值转换为字符,这一直让我困扰。您会如何解决这个问题? - Waldir Leoncio
2
@JeromyAnglim 我注意到上面的解决方案可能存在一个边缘情况的缺点,即固定小数点前的数字个数,例如format(c(10, 1), nsmall=1)会产生 "10.0" " 1.0"(请注意1.0前面的空格)。而sprintf()函数似乎保证了小数点两侧更好的格式,例如sprintf(c(10,1), fmt = '%#.1f')可以去掉那个讨厌的前导空格,并返回"10.0" "1.0" - Nicholas G Reich
4
前导空格是一种特性,旨在使使用format格式化结果时,在列中对齐小数点。 - Inhabitant
1
@FengJiang 这不是函数的问题,而是你应该避免将 digits 选项设置得太高。请参见 print.default 帮助文档 中的警告。它警告说,设置 digits >=16 可能会导致打印问题。 - Jeromy Anglim
显示剩余10条评论

53

您可以根据自己的需要将一个数字格式化为指定小数位数。这里的x是一个带有许多小数位的数字。假设我们希望显示该数字的8位小数:

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

在这里,format="f"会以通常小数点后的数字显示浮点数,例如xxx.xxx,而digits则指定了显示的位数。相反地,如果你想要显示一个整数,你应该使用format="d"(就像sprintf一样)。


2
虽然我不确定OP确切在问什么,但根据最高评分的答案,我不禁观察到formatC几乎是我用于此目的的唯一选择。我认为这个答案很好,并且符合OP的要求使用基本R。 - AdamO
这个答案比被选中的答案更好。formatC不受options(digits)的影响。 - Feng Jiang

37

你可以尝试使用我的包 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只会对某些列进行四舍五入显示。我需要解决这个问题,因为我还需要对这些列进行计算。现在问题已经解决了,谢谢! - thethakuri
2
我更喜欢formattable胜过任何baseR函数。它最大的优势是保留变量为数字。 - Lazarus Thurston

33

保留尾随零的情况下保留2位小数

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

提供

[1] "5.50"

正如@mpag在下面提到的,似乎R有时会在使用此方法和round方法时给出意外的值,例如sprintf(5.5550,fmt ='%#.2f')会给出5.55而不是5.56


1
然而,尽管sprintf进行了四舍五入,但是sprintf(5.5550, fmt='%#.2f')会给出一个稍微意外的结果:5.55。sprintf(5.555000000001, fmt='%#.2f')则会得到5.56。这似乎是R中四舍五入的一个普遍“问题”,因为round和nsmall方法也会产生相同的结果。 - mpag
谢谢@mpag,我不知道R在边界上四舍五入时会有困难,我刚刚尝试了一下5.565,它确实向上舍入,而5.545则向下舍入。我猜这是他们处理浮点数不精确性的方式。我想我没有在其他语言中看到过这种行为,这意味着它们可能有内置的解决方法。 - Mark Adamson
我认为他们有意地将值的精度限制在一定程度上。他们认为一个值5.555实际上与5.5546或5.5554这些“真实”值同样可能。然而,如果你继续这种舍入游戏,5.444445(未经测试)可能会在逐位进行舍入时变成“6”。但你说得对,这可能是二进制表示略微低于或高于5.55的问题。 - mpag
是的,我认为如果这是有意的话,在5.565和5.545之间应该是一致的。这种“随机性”让我觉得这是浮点表示的问题。 - Mark Adamson

12

类似这样:

options(digits=2)

digits选项的定义:

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

运行脚本时有没有办法动态设置这个? - Brandon Bertelsen
这个可以在R控制台中输出,但在我的脚本中不起作用(它们仍然以.1289273982的形式输出)。 - Brandon Bertelsen
2
我遇到了奇怪的行为,digits选项似乎不能设置小数点后的位数。例如,当我设置options(digits = 2)时,打印7.25的结果是7.2,1234.25变成了1234,而0.25仍然是0.25。是否有其他选项与此交互? - Maxim.K
如果您只需要一次使用,那么绝对不应该这样做。更改选项将影响所有内容。 - Feng Jiang

12
如果您更喜欢有效数字而不是固定数字,则可能会发现 signif 命令有用:
> signif(1.12345, digits = 3)
[1] 1.12
> signif(12.12345, digits = 3)
[1] 12.1
> signif(12345.12345, digits = 3)
[1] 12300

1
谢谢Paul。这两个不是我想要的,但是signif让我找到了round(),这正是我需要的。干杯! - Brandon Bertelsen
34
错误:找不到函数“fixed”。 - ThomasH
1
signif函数适用于特定的数字,但我猜想常见的应用问题是当你需要显示恰好两位小数,但事先不知道数字时。在这种情况下,signif将根据实际数字给出不同数量的小数位数。 - Jeromy Anglim
3
固定值未在任何地方找到。请修复,否则这个误导性的答案应该被删除。 - ABCD
@JeromyAnglim 我们如何解决需要3位有效数字的问题?有时它会给我3位有效数字,有时是4位等等。我们该如何解决这个问题? - christouandr7

10

检查函数prettyNum, format

如果需要保留尾部零(例如123.1240),使用sprintf(x, fmt='%#.4g')


@42 我建议学习 sprintf,它基本上是一个格式化框架。 - jangorecki
1
@jangorecki,我不确定你的观点。我所做的(5年前)只是建议一个拼写更正。 - IRTFM
@42 我以为你在抱怨 fmt 参数,抱歉! - jangorecki
1
我认为OP想要固定小数位,而不是固定数字。你回答中的g似乎是用于固定数字的,使用f更好。 - Mark Adamson

6

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


4
我使用这个变量来强制打印K位小数:
# format numeric value to K decimal places
formatDecimal <- function(x, k) format(round(x, k), trim=T, nsmall=k)

3
请注意,R语言中的数字对象使用双精度存储,这会给您(大约)16个十进制数字的精度 - 其余部分将是噪声。我承认上面显示的数字只是一个示例,但它有22个数字长度。

3
确认,这只是个例子。我随意乱按了键盘。 - Brandon Bertelsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接