在将数字列表转换为字符时,如何控制数字的格式?

时间:2016-05-04 10:32:39

标签: r formatting

我有一个包含数字的嵌套列表,例如

x <- list(1 + .Machine$double.eps, list(rnorm(2), list(rnorm(1))))

如果我就此致电as.character,则所有数字均以固定格式提供,为15位有效数字。

as.character(x)
## [1] "1"                                                                      
## [2] "list(c(0.654345721043012, 0.611306113713901), list(-0.278722330674071))"

我希望能够控制数字的格式化方式。至少,我希望能够控制包含多少重要数字。作为奖励,能够指定科学格式而不是固定格式将是很好的。

?as.character帮助页面说明:

  

as.character表示实数和复数到15显着   数字(技术上是编译器对ISO C常数的设置)   DBL_DIG,在支持IEC60559算术的机器上将是15   根据C99标准)。这确保了所有数字   结果将是可靠的(而不是表示的结果   错误),但确实意味着转换为字符并返回数字   可能会改变这个数字。如果要将数字转换为字符   以最大可能的精度,使用格式。

因此,似乎无法直接使用as.character更改格式。

调用format会破坏列表结构:

format(x, digits = 5)
## [1] "1"                          "0.65435, 0.61131, -0.27872"

formatC会抛出一个关于不支持列表输入的错误。

deparse也不允许用户更改数字的格式:as.character(x)vapply(x, deparse, character(1))相同。

这几乎是正确的,但在我不想要的数字周围有额外的双引号字符:

as.character(rapply(x, format, digits = 5, how = "list"))
## [1] "1"
## [2] "list(c(\"0.65435\", \"0.61131\"), list(\"-0.27872\"))"

如何控制数字的格式?

部分解决方案:为了减少有效数字的数量,我可以通过使用格式转换为字符,然后返回数字来调整前面的示例。

as.character(rapply(x, function(x) as.numeric(format(x, digits = 5)), how = "list"))
## [1] "1"                                       "list(c(-1.0884, 1.6892), list(0.58783))"

如果我想增加超过15的sig figs数量或使用科学格式(因为我们遇到as.character的限制),这不起作用。

as.character(rapply(x, function(x) as.numeric(format(x, digits = 22)), how = "list"))
## [1] "1"                                                                  
## [2] "list(c(-1.08842504028146, 1.68923191896784), list(0.5878275490431))"

2 个答案:

答案 0 :(得分:3)

使用how参数播放rapply()

> rapply(x, sprintf, fmt = "%0.5f", how = "replace")
[[1]]
[1] "1.00000"

[[2]]
[[2]][[1]]
[1] "0.18041"  "-0.63925"

[[2]][[2]]
[[2]][[2]][[1]]
[1] "0.14309"

要获得更多数字,请更改fmt

> rapply(x, sprintf, fmt = "%0.22f", how = "replace")
[[1]]
[1] "1.0000000000000002220446"

[[2]]
[[2]][[1]]
[1] "1.2888001496908956244880" "1.0289289081633956612905"

[[2]][[2]]
[[2]][[2]][[1]]
[1] "0.4656598705611921240610"

您可以gsub()引号:

> gsub("\"", "", deparse(rapply(x, function(z) sprintf(fmt = "%0.22f", z), how = "replace")))
[1] "list(1.0000000000000002220446, list(c(1.2888001496908956244880, "
[2] "1.0289289081633956612905), list(0.4656598705611921240610)))"

答案 1 :(得分:0)

R Core成员Martin Maechler给我的建议是,你可以用"%g17"样式格式化数字(即R决定固定格式或科学格式是否最佳,并将有效数字的数量增加到17 ;使用deparse和?sprintf controls选项查看"digits17")。后者记录在?.deparseOpts帮助页面上。

vapply(x, deparse, character(1), control = "digits17")