在 R 中控制打印输出中的小数位数

在 R 中有一个选项可以控制数字显示。例如:

options(digits=10)

在 R 会话结束前,应该给出10位数的计算结果。在 R 的帮助文件中,数字参数的定义如下:

数字: 控制数字的数量 在打印数值时打印。 这只是一个建议。有效的价值观 是 1... 22,默认值 < strong > 7

所以,它说这只是一个建议。如果我总是显示10个数字,而不是更多或更少呢?

我的第二个问题是,如果我想显示多于22个数字,即更精确的计算,如100个数字,该怎么办?是否可以使用基本 R,或者我需要一个额外的包/函数来实现这一点?

编辑: 感谢 jmoy 的建议,我尝试了 sprintf("%.100f",pi),它给了

[1] "3.1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000"

有48个小数,这是 R 能处理的最大限制吗?

292445 次浏览

如果您自己生成整个输出,则可以使用 sprintf(),例如。

> sprintf("%.10f",0.25)
[1] "0.2500000000"

指定希望将浮点数格式化为十个小数点(在 %.10f中,f表示浮点数,而 .10指定十个小数点)。

我不知道有什么方法可以强制 R 的高级函数输出精确的数字数。

如果打印的是 R 的通常数字,显示100位数字是没有意义的,因为使用64位双精度数所能得到的最佳准确度大约是16位小数位(请看。系统上的 Machine $double.ep)。剩下的数字都是垃圾。

之所以只是一个建议,是因为您可以很容易地编写一个忽略选项值的打印函数。内置的打印和格式化函数确实使用 options值作为默认值。

至于第二个问题,因为 R 使用有限精度的算术,你的答案不会精确到超过15或16个小数位,所以一般来说,不需要更多。GMP刚果民主共和国包处理高精度计算(通过与 gmp 库的接口) ,但这主要与大整数有关,而不是与双精度数的小数位有关。

Mathematica 或者 枫树将允许你给出你内心想要的小数点后的位数。

编辑:
考虑一下小数位和重要数字之间的差别可能会有用。如果你所做的统计测试依赖于第15个显著数字以外的差异,那么你的分析几乎肯定是垃圾。

另一方面,如果您只是处理非常小的数字,那就没什么问题了,因为 R 可以处理 .Machine$double.xmin这样小的数字(通常是2e-308)。

比较这两个分析。

x1 <- rnorm(50, 1, 1e-15)
y1 <- rnorm(50, 1 + 1e-15, 1e-15)
t.test(x1, y1)  #Should throw an error


x2 <- rnorm(50, 0, 1e-15)
y2 <- rnorm(50, 1e-15, 1e-15)
t.test(x2, y2)  #ok

在第一种情况下,数字之间的差异只出现在许多有意义的数字之后,因此数据是“几乎不变的”。在第二种情况下,虽然数字之间的差异的大小是相同的,但是与数字本身的大小相比,它们是很大的。


正如 e3bo 所提到的,可以使用 Rmpfr包使用多精度浮点数。

mpfr("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825")

与常规(双精度) numeric向量相比,这些向量的使用速度更慢,内存密集程度更高,但是如果您遇到条件较差的问题或算法不稳定,这些向量可能非常有用。

还有一个解决方案,可以根据需要控制打印多少个小数位(如果您不想打印冗余的零)

例如,如果你有一个矢量作为 elements,并希望得到它的 sum

elements <- c(-1e-05, -2e-04, -3e-03, -4e-02, -5e-01, -6e+00, -7e+01, -8e+02)
sum(elements)
## -876.5432

显然,最后的数字作为 1被截断,理想的结果应该是 -876.54321,但如果设置为固定打印小数选项,例如 sprintf("%.10f", sum(elements)),冗余零(s)生成为 -876.5432100000

按照这里的教程: 打印十进制数,如果能够识别在某个数字中有多少个小数位,像这里的 -876.54321,有5个小数位需要打印,那么我们可以为 format函数设置一个参数如下:

decimal_length <- 5
formatC(sum(elements), format = "f", digits = decimal_length)
## -876.54321

我们可以根据每次查询更改 decimal_length,以满足不同的十进制打印要求。

如果主要使用 tibble,则有一个函数强制执行数字: num()

这里有一个例子:

library(tidyverse)


data <- tribble(
  

~ weight, ~ weight_selfreport,
81.5,81.66969147005445,
72.6,72.59528130671505,
92.9,93.01270417422867,
79.4,79.4010889292196,
94.6,96.64246823956442,
80.2,79.4010889292196,
116.2,113.43012704174228,
95.4,95.73502722323049,
99.5,99.8185117967332
)


data <-
data %>%
mutate(across(where(is.numeric), ~ num(., digits = 3)))


data
#> # A tibble: 9 × 2
#>      weight weight_selfreport
#>   <num:.3!>         <num:.3!>
#> 1    81.500            81.670
#> 2    72.600            72.595
#> 3    92.900            93.013
#> 4    79.400            79.401
#> 5    94.600            96.642
#> 6    80.200            79.401
#> 7   116.200           113.430
#> 8    95.400            95.735
#> 9    99.500            99.819

因此,您甚至可以根据您的需求决定不同的舍入选项。我发现它非常有用,是打印 dfs 的一个非常快速的解决方案。