【问题标题】:How to format numbers in R, specifying the number of significant digits but keep significant zeroes and integer part?如何在 R 中格式化数字,指定有效位数但保留有效零和整数部分?
【发布时间】:2014-02-26 20:40:02
【问题描述】:

我一直在努力使用我认为非常明智的规则来格式化 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
}

【问题讨论】:

    标签: r formatting number-formatting


    【解决方案1】:

    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。

    EDIT 这似乎处理了@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" 
    

    【讨论】:

    • 嗯,我相信您的解决方案不会按照我的意图处理例如 0.5 或 0.005。 sigDigits(0.00500, 3) 导致0.005,而我认为它应该导致0.00500。 IO 已经用受您启发的答案编辑了我的问题,我认为(希望)适用于所有情况。 :)
    【解决方案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"
    

    【讨论】:

    • 嗯,缩进的用法是为了更好地格式化数字。我不是科学记数法的忠实粉丝。谢谢你们的回答,如果可以的话,我会接受的。我掷硬币,吉霍华德赢了。
    • @jlhoward 使用该函数编辑的答案解决了更广泛数字的问题。这对其他想要类似东西的人会有所帮助,因此它应该成为公认的答案 =)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-24
    • 2010-09-14
    • 1970-01-01
    • 2014-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多