简体   繁体   English

在 R 中将数字格式化为有效数字

[英]Format numbers to significant figures nicely in R

I want to format numbers in my reports to significant digits , but keep trailing significant zeroes and correctly format large numbers我想将报告中的数字格式化为有效数字,但保留尾随有效零并正确格式化大数字

For instance the numbers c(10.00001,12345,1234.5,123.45,1.2345,0.12345) to 3 significant digits should be 10.0, 12300, 1230, 123, 1.23, 0.123 but I get differing results with different methods (and none seem to work universaly.例如,数字 c(10.00001,12345,1234.5,123.45,1.2345,0.12345) 到 3 位有效数字应该是 10.0, 12300, 1230, 123, 1.23, 0.123 但我用不同的方法得到不同的结果(而且似乎没有一个普遍适用.

> numbers<-c(10.00001,12345,1234.5,123.45,1.2345,0.12345)
> for(n in seq(numbers)){
+   print(signif(numbers[n],digits=3))
+   print(format(numbers[n],digits=3))
+   print(formatC(numbers[n], digits=3,format="fg"))
+   print(formatC(numbers[n], digits=3,format="fg", flag="#"))
+   }
[1] 10
[1] "10"
[1] "  10"
[1] "10.0"
[1] 12300
[1] "12345"
[1] "12345"
[1] "12345."
[1] 1230
[1] "1234"
[1] "1234"
[1] "1234."
[1] 123
[1] "123"
[1] " 123"
[1] "123."
[1] 12.3
[1] "12.3"
[1] "12.3"
[1] "12.3"
[1] 1.23
[1] "1.23"
[1] "1.23"
[1] "1.23"
[1] 0.123
[1] "0.123"
[1] "0.123"
[1] "0.123"

Here, signif and format round the 10.00001 result.在这里,对 10.00001 结果进行符号化和格式化。 formatC with flag="#" correctly does the small numbers but not the large numbers.带有 flag="#" 的 formatC 正确地处理小数字而不是大数字。

Is there a better way?有没有更好的办法?

Sorry I never updated this at the time. 抱歉,我当时没有更新。 None of the statements in my question, or prettynum worked. 我的问题或prettynum中的任何陈述均无用。 In the end I used 最后我用了

print(formatC(signif(numbers[n],digits=3), digits=3,format="fg", flag="#"))

which correctly coped with trailing zero's and big numbers. 正确处理了尾随零和大数的问题。

您是否知道prettyNum()及其所有选项?

A more barebones option is options() , which just does rounding. 更为准系统的选项是options() ,它只进行舍入。 If you plan on doing this a lot, I suggest checking out Sweave. 如果您打算做很多事情,建议您检查Sweave。

> a <- 1.23456789
> options(digits=2)
> a
[1] 1.2
> options(digits=6)
> a
[1] 1.23457

Another modification on Paul's answer. 保罗的回答的另一种修改。 It appears that it also leaves a trailing decimal. 似乎还留下了尾随的小数。 I am removing it with gsub: 我用gsub删除它:

sigfig <- function(vec, digits){
  return(gsub("\\.$", "", formatC(signif(vec,digits=digits), digits=digits, format="fg", flag="#")))
}

Paul Hurley's method above worked well for me for both positive and negative numbers. Paul Hurley的上述方法对于正数和负数都对我有效。 Below is some code which modifies Paul's solution into a function in which the desired significant figures can be specified. 以下是一些代码,这些代码将Paul的解决方案修改为可以指定所需有效数字的函数。

sigfig <- function(vec, n=3){ 
### function to round values to N significant digits
# input:   vec       vector of numeric
#          n         integer is the required sigfig  
# output:  outvec    vector of numeric rounded to N sigfig

formatC(signif(vec,digits=n), digits=n,format="fg", flag="#") 

}      # end of function   sigfig

to verify it works OK 验证它可以正常工作

numbers <- c(50000.01, 1000.001, 10.00001, 12345, 1234.5, 123.45, 1.2345, 0.12345, 0.0000123456, -50000.01, -1000.001,-10.00001, -12345, -1234.5, -123.45, -1.2345, -0.12345, -0.0000123456)
sigfig(numbers)   # defaults to 3
sigfig(numbers, 3)
sigfig(numbers, 1)
sigfig(numbers, 6)

If you like scientific notation 如果您喜欢科学记数法

> format(2^31-1, scientific = TRUE, digits = 3)
[1] "2.15e+09"

The following option replicates the format of formatC(format="fg",flag="#") ( fg is a special version of f where the digits specify significant digits and not digits after the decimal point, and the # flag causes fg to not drop trailing zeroes):以下选项复制formatC(format="fg",flag="#")的格式( fgf的特殊版本,其中数字指定有效数字而不是小数点后的数字, #标志导致fg不删除尾随零):

> f=2;x=c(10000.0001,1111,111.11,11.1,1.1,1.99,.01,.001,0,-.11,-.9,-.000011)
> dig=abs(pmin(0,floor(log10(abs(x)))-f+1))
> sprintf(paste0("%.",ifelse(is.infinite(dig),0,dig),"f"),x)
 [1] "10000"     "1111"      "111"       "11"        "1.1"       "2.0"
 [7] "0.010"     "0.0010"    "0"         "-0.11"     "-0.90"     "-0.000011"
> sub("\\.$","",formatC(x,f,,"fg","#"))
 [1] "10000"     "1111"      "111"       "11"        "1.1"       "2.0"
 [7] "0.010"     "0.0010"    "0"         "-0.11"     "-0.90"     "-0.000011"

I found a potentially unwanted behaviour with the answer presented by PaulHurleyuk:我在 PaulHurleyuk 提供的答案中发现了潜在有害行为:

Tests测试

Test 1:测试 1:

numbers <- c(0.0001, 0.001, 0.01, 0.1, 1, 10, 100, 1000)
print(formatC(signif(numbers, digits = 3), digits = 3, format = "fg", flag = "#"))

Returns:退货:

[1] "0.000100" "0.00100"  "0.0100"   "0.100"    "1.00"     "10.0"     "100."     "1000."

Test 2:测试 2:

numbers <- c(1.0001, 1.001, 1.01, 1.1, 11, 101, 1001, 10001)
print(formatC(signif(numbers,digits=3), digits=3,format="fg", flag="#"))

Returns:退货:

[1] "1.00"   "1.00"   "1.01"   "1.10"   "11.0"   "101."   "1000."  "10000."

Notice the trailing decimal delimiters in both examples and also the introduced trailing zeros in test 1.请注意两个示例中的尾随小数分隔符以及测试 1 中引入的尾随零。

Solution解决方案

To remove the trailing decimal delimiters:要删除尾随的小数分隔符:

gsub("\\.$", "", formatC(signif(numbers, digits = 3), digits = 3,format = "fg", flag = "#"))

If used often, make it a function:如果经常使用,将其设置为 function:

sigfill <- function(x, sigfigs = 3){
  out <- gsub("\\.$", "",
              formatC(signif(x, digits = sigfigs),
                      digits = sigfigs, format = "fg", flag = "#"))
  return(out)
}

To also remove trailing zeros introduced by the previous code:还要删除前面代码引入的尾随零:

sigfill <- function(x, sigfigs = 3){
  out <- gsub("\\.$", "",
              formatC(signif(x, digits = sigfigs),
                      digits = sigfigs, format = "fg", flag = "#"))
  out[grepl(".", out, fixed = TRUE)] <- strtrim(out[grepl(".", out, fixed = TRUE)],
                                                sigfigs + c(1, 2)[grepl("-", out, fixed = TRUE) + 1])
  return(out)
}

Test again再次测试

Positive numbers:正数:

numbers <- c(0.0001, 0.001, 0.01, 0.1, 1, 10, 100, 1000)
sigfill(numbers)

returns回报

[1] "0.00" "0.00" "0.01" "0.10" "1.00" "10.0" "100"  "1000"

"Spread out" numbers: “展开”数字:

numbers <- c(1.0001, 1.001, 1.01, 1.1, 11, 101, 1001, 10001)
sigfill(numbers)

returns回报

[1] "1.00"  "1.00"  "1.01"  "1.10"  "11.0"  "101"   "1000"  "10000"

Negative numbers:负数:

numbers <- c(-0.0001, -0.001, -0.01, -0.1, -1, -10, -100, -1000)
sigfill(numbers)

returns回报

[1] "-0.00" "-0.00" "-0.01" "-0.10" "-1.00" "-10.0" "-100"  "-1000"

Result: No trailing decimal delimiters or additional trailing zeros.结果:没有尾随小数分隔符或附加尾随零。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM