如何格式化R中的数字,指定有效位数但保留重要的零和整数部分?

时间:2014-02-03 11:21:55

标签: r formatting number-formatting

我一直在努力使用我觉得非常明智的规则来格式化R中的数字。我想要的是指定一些有效数字(比如3),保持显着的零,并保留小数点前的所有数字,一些例子(有3位有效数字):

1.23456 -> "1.23"
12.3456 -> "12.3"
123.456 -> "123"
1234.56 -> "1235"
12345.6 -> "12346"
1.50000 -> "1.50"
1.49999 -> "1.50"

R中是否有一个执行此类格式化的功能?如果没有,怎么办呢?

我觉得这些是非常明智的格式规则,但我还没有设法在R中找到以这种方式格式化的函数。据我搜索,这不是许多类似问题的重复,例如this

编辑:

受到两个好答案的启发,我自己编写了一个函数,我相信它适用于所有情况:

sign_digits <- function(x,d){
  s <- format(x,digits=d)
  if(grepl("\\.", s) && ! grepl("e", s)) {
    n_sign_digits <- nchar(s) - 
      max( grepl("\\.", s), attr(regexpr("(^[-0.]*)", s), "match.length") )
    n_zeros <- max(0, d - n_sign_digits)
    s <- paste(s, paste(rep("0", n_zeros), collapse=""), sep="")
  }
  s
}

2 个答案:

答案 0 :(得分:6)

format(num,3)非常接近。

format(1.23456,digits=3)
# [1] "1.23"
format(12.3456,digits=3)
# [1] "12.3"
format(123.456,digits=3)
# [1] "123"
format(1234.56,digits=3)
# [1] "1235"
format(12345.6,digits=3)
# [1] "12346"
format(1.5000,digits=3)
# [1] "1.5"
format(1.4999,digits=3)
# [1] "1.5"

您的规则实际上并非内部一致。您希望1234.56向下舍入到1234,但您希望1.4999向上舍入到1.5。

编辑这似乎是为了处理@Henrik提出的非常有效的观点。

sigDigits <- function(x,d){
  z <- format(x,digits=d)
  if (!grepl("[.]",z)) return(z)
  require(stringr)
  return(str_pad(z,d+1,"right","0"))
}

z <- c(1.23456, 12.3456, 123.456, 1234.56, 12345.6, 1.5000, 1.4999)
sapply(z,sigDigits,d=3)
# [1] "1.23"  "12.3"  "123"   "1235"  "12346" "1.50"  "1.50" 

答案 1 :(得分:2)

正如@jlhoward指出的那样,你的舍入规则并不一致。因此,您应该使用条件语句:

x <- c(1.23456, 12.3456, 123.456, 1234.56, 12345.6, 1.50000, 1.49999) 
ifelse(x >= 100, sprintf("%.0f", x), ifelse(x < 100 & x >= 10, sprintf("%.1f", x), sprintf("%.2f", x)))
# "1.23"  "12.3"  "123"   "1235"  "12346" "1.50"  "1.50"

很难说出预期的用法,但使用一致的舍入可能会更好。指数表示法可以是一个选项:

sprintf("%.2e", x)
[1] "1.23e+00" "1.23e+01" "1.23e+02" "1.23e+03" "1.23e+04" "1.50e+00" "1.50e+00"