我想使用
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)。
为了说明我在评论中所说的内容,你可以这样做:
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 )
在
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 )"