使用带有 2 个有效数字的 formatC 的奇怪输出

问题描述 投票:0回答:2

我想使用

formatC
将数字格式化为 2 位有效数字。但它有一个奇怪的行为。以下是数字:

(x <- data.frame(  cil = c(1.234, 0.444, 0.712, 0.999, 1.999)
                 , ciu = c(1.812, 1.234, 0.999, 1.199, 2.690)
                 )
 )
 
x$ci <- with(x,paste("("
              , formatC(cil, format="g", digits=2, flag="#")
              , "-"
              , formatC(ciu, format="g", digits=2, flag="#")
              ,")"
                      )
              )
x

结果如下:

      cil   ciu         ci
1     1.234 1.812  ( 1.2 - 1.8 )
2     0.444 1.234 ( 0.44 - 1.2 )
3     0.712 0.999 ( 0.71 - 1.0 )
4     0.999 1.199  ( 1.0 - 1.2 )
5     1.999 2.690  (  2. - 2.7 )

在情况 5 中,我预期为 2.0 而不是 2.。对此有解释吗?是我参数定义有问题吗?

新的奇怪行为:前导空格取决于数字是向下还是向上舍入:

y1 <- 18.96552
y2 <- 17.04545
formatC(y1, format="g", digits=2,flag="#")
[1] "  19."
formatC(y2, format="g", digits=2,flag="#")
"17."

可以用trim(来自gdata)来解决。但无论如何,与第一个行为一样,这是一个奇怪的行为,顺便说一句,它仍然存在(V4.32)。

r format significant-digits
2个回答
1
投票

为了说明我在评论中所说的内容,你可以这样做:

x$ci<-with(x,paste("(",
                   format(cil,digits=2,nsmall=2),
                   "-",
                   format(ciu,digits=2,nsmall=2),")"))
> x
  case   cil   ciu              ci
1    A 1.234 1.812 ( 1.23 - 1.81 )
2    B 0.444 1.234 ( 0.44 - 1.23 )
3    C 0.712 0.999 ( 0.71 - 1.00 )
4    D 0.999 1.199 ( 1.00 - 1.20 )
5    E 1.999 2.690 ( 2.00 - 2.69 )

或以下内容,以抑制括号之前或之后的空格:

x$ci<-with(x,paste0("(",
                    format(cil,digits=2,nsmall=2),
                    " - ",
                    format(ciu,digits=2,nsmall=2),")"))
> x
  case   cil   ciu          ci
1    A 1.234 1.812 (1.23 - 1.81)
2    B 0.444 1.234 (0.44 - 1.23)
3    C 0.712 0.999 (0.71 - 1.00)
4    D 0.999 1.199 (1.00 - 1.20)
5    E 1.999 2.690 (2.00 - 2.69)

NB:实际上,您可以使用函数

formatC
获得相同的结果,但使用
format="f"
而不是
"g"

更新:

我猜在

0
之后不打印
2.
的事实只是某些 R 版本中的一个错误(奇怪的事情:如果你尝试使用
2.01
而不是
1.999
,你会得到
"2.0"
) ...).

要使其与您的生产线配合并获得您想要的结果,只需添加

round
功能:

x$ci<-with(x,paste("(",
                    formatC(round(cil,2), format="g", digits=2, flag="#"),
                   "-",
                   formatC(round(ciu,2), format="g", digits=2, flag="#"),")"))

> x
  case   cil   ciu             ci
1    A 1.234 1.812  ( 1.2 - 1.8 )
2    B 0.444 1.234 ( 0.44 - 1.2 )
3    C 0.712 0.999 ( 0.71 - 1.0 )
4    D 0.999 1.199  ( 1.0 - 1.2 )
5    E 1.999 2.690  ( 2.0 - 2.7 )

1
投票

R 3.1.2
上使用
linux mint 17
,我无法重现该问题,因为我得到的结果与您的预期输出完全相同。但是,如果您有很多列(或一般情况下),可以选择将
paste
do.call
一起使用

1) 使用格式C

x$ci <- paste0("(",do.call(`paste`, c(lapply(x[,2:3], function(x) 
 formatC(x, format='g',   digits=2, flag='#')), list(sep=" - "))) ,")")
x$ci
#[1] "(1.2 - 1.8)"  "(0.44 - 1.2)" "(0.71 - 1.0)" "(1.0 - 1.2)"  "(2.0 - 2.7)" 

注意:以上与预期输出完全相同。

2)使用 sprintf

我考虑的另一个选择是使用

sprintf
如果您需要与更新前 @CathG 显示的类似输出

x$ci <- paste0("(",do.call(`paste`, c(lapply(x[2:3], function(x) 
                       sprintf('%0.2f', x)), list(sep="-"))),")")
x$ci
#[1] "(1.23-1.81)" "(0.44-1.23)" "(0.71-1.00)" "(1.00-1.20)" "(2.00-2.69)"

更新

您可以使用

regex
来解决问题。例如,我创建了与输出相同的
5th
条目,并使用正则表达式
lookbehind

x$ci[5] <- "( 2. - 2.7 )"
sub('(?<=\\.) ', '0', x$ci, perl=TRUE)
#[1] "( 1.2 - 1.8 )"  "( 0.44 - 1.2 )" "( 0.71 - 1.0 )" "( 1.0 - 1.2 )" 
#[5] "( 2.0- 2.7 )"  
© www.soinside.com 2019 - 2024. All rights reserved.