How do you control the formatting of digits when converting lists of numbers to character?

偶尔善良 提交于 2021-02-10 06:31:57

问题


I have a nested list containing numbers, for example

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

If I call as.character on this, all the numbers are given in fixed format, to 15 significant digits.

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

I'd like to be able to control how the numbers are formatted. At the very least, I'd like to be able to control how many significant figures are included. As a bonus, being able to specify scientific formatting rather than fixed formatting would be nice.

The ?as.character help page states:

as.character represents real and complex numbers to 15 significant digits (technically the compiler's setting of the ISO C constant DBL_DIG, which will be 15 on machines supporting IEC60559 arithmetic according to the C99 standard). This ensures that all the digits in the result will be reliable (and not the result of representation error), but does mean that conversion to character and back to numeric may change the number. If you want to convert numbers to character with the maximum possible precision, use format.

So it doesn't appear to be possible to change the formatting using as.character directly.

Calling format destroys the list structure:

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

formatC throws an error about not supporting list inputs.

deparse also doesn't allow users to change how numbers are formatted: as.character(x) is the same as vapply(x, deparse, character(1)).

This is almost correct, but there are extra double-quote characters around the numbers that I don't want:

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

How do I control the formatting of the numbers?


A partial solution: for reducing the number of significant figures, I can adapt the previous example by converting to character using format, then back to numeric.

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))"

This doesn't work if I want to increase the number of sig figs beyond 15 or use scientific formatting (since we run into the limitation of 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))"

回答1:


Play with the how argument to 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"

For more digits, change 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"

You can gsub() out the quotes:

> 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)))"



回答2:


Advice given to me by R Core member Martin Maechler was that you can format the numbers in a "%g17" style (that is R decides whether fixed or scientific formatting is best, and increases the number of significant digits to 17; see ?sprintf) by using deparse and the "digits17" controls option. The latter is documented on the ?.deparseOpts help page.

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


来源:https://stackoverflow.com/questions/37025196/how-do-you-control-the-formatting-of-digits-when-converting-lists-of-numbers-to

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!