如何在R中将数字格式化为百分比?

其中一个让我感到困惑的事情就是如何将数字格式化为打印的百分比。

例如,显示0.1234512.345% 。 对此我有一些解决方法,但是这些都不是“友好的”。 例如:

 set.seed(1) m <- runif(5) paste(round(100*m, 2), "%", sep="") [1] "26.55%" "37.21%" "57.29%" "90.82%" "20.17%" sprintf("%1.2f%%", 100*m) [1] "26.55%" "37.21%" "57.29%" "90.82%" "20.17%" 

问:是否有一个基本的R函数来做到这一点? 另外,是否有一个广泛使用的包提供了一个方便的包装?


尽pipe在?format?formatC?prettyNum寻找这样的东西,我还没有find一个适当的方便包装在基地R. ??"percent"没有产生任何有用的东西。 library(sos); findFn("format percent") library(sos); findFn("format percent")返回1250点 – 所以再次没有用。 ggplot2有一个函数percent但是这不能控制舍入精度。

数年后的更新:

这些日子里,衡量包中有一个percent函数,正如krlmlr的答案中所logging的那样。 使用这个,而不是我的手卷解决scheme。


尝试类似

 percent <- function(x, digits = 2, format = "f", ...) { paste0(formatC(100 * x, format = format, digits = digits, ...), "%") } 

随着使用,例如,

 x <- c(-1, 0, 0.1, 0.555555, 1, 100) percent(x) 

(如果您愿意,请将格式从"f"更改为"g" 。)

检查scales包。 它曾经是ggplot2的一部分,我想。

 library('scales') percent((1:10) / 100) # [1] "1%" "2%" "3%" "4%" "5%" "6%" "7%" "8%" "9%" "10%" 

用于检测精度的内置逻辑在大多数情况下应该可以正常工作。

 percent((1:10) / 1000) # [1] "0.1%" "0.2%" "0.3%" "0.4%" "0.5%" "0.6%" "0.7%" "0.8%" "0.9%" "1.0%" percent((1:10) / 100000) # [1] "0.001%" "0.002%" "0.003%" "0.004%" "0.005%" "0.006%" "0.007%" "0.008%" # [9] "0.009%" "0.010%" percent(sqrt(seq(0, 1, by=0.1))) # [1] "0%" "32%" "45%" "55%" "63%" "71%" "77%" "84%" "89%" "95%" # [11] "100%" percent(seq(0, 0.1, by=0.01) ** 2) # [1] "0.00%" "0.01%" "0.04%" "0.09%" "0.16%" "0.25%" "0.36%" "0.49%" "0.64%" # [10] "0.81%" "1.00%" 

检查formattable包中的percent函数:

 library(formattable) x <- c(0.23, 0.95, 0.3) percent(x) [1] 23.00% 95.00% 30.00% 

这里是我定义一个新function的解决scheme(主要是我可以使用Curry和Compose :-)):

 library(roxygen) printpct <- Compose(function(x) x*100, Curry(sprintf,fmt="%1.2f%%")) 

我为这些答案的速度做了一些基准testing,并且很惊讶地发现由于它的低迷,在scales包中的percent如此被吹捧。 我认为它的优点是它的自动检测器适合格式化,但是如果你知道你的数据是什么样子的话,似乎很清楚要避免。

以下是试图将(0,1)中100,000个百分比列表格式化为2位数百分比的结果:

 library(microbenchmark) x<-runif(1e5) microbenchmark(times=100L,andrie1(),andrie2(),richie(),krlmlr()) Unit: milliseconds expr min lq mean median uq max 1 andrie1() 91.08811 95.51952 99.54368 97.39548 102.75665 126.54918 #paste(round()) 2 andrie2() 43.75678 45.56284 49.20919 47.42042 51.23483 69.10444 #sprintf() 3 richie() 79.35606 82.30379 87.29905 84.47743 90.38425 112.22889 #paste(formatC()) 4 krlmlr() 243.19699 267.74435 304.16202 280.28878 311.41978 534.55904 #scales::percent() 

所以当我们想要添加一个百分号的时候, sprintf就成了一个明显的赢家。 另一方面,如果我们只想把数字和数字相乘(从比例到没有“%”的百分比,那么round()是最快的:

 Unit: milliseconds expr min lq mean median uq max 1 andrie1() 4.43576 4.514349 4.583014 4.547911 4.640199 4.939159 # round() 2 andrie2() 42.26545 42.462963 43.229595 42.960719 43.642912 47.344517 # sprintf() 3 richie() 64.99420 65.872592 67.480730 66.731730 67.950658 96.722691 # formatC() 

你可以使用scale包来进行这个操作(不需要加载require或者库)

 scales::percent(m) 

看到scalable::percent已经被certificate是最慢的,而Liliana Pacheco提供了另一种解决scheme,我继续尝试将其与其他一些基于Michael设置的选项进行比较:

 library(microbenchmark) library(scales) library(formattable) x<-runif(1e5) lilip <- function() formattable::percent(x,2) krlmlr <- function() scales::percent(x) andrie1 <- function() paste0(round(x,4) * 100, '%') microbenchmark(times=100L,lilip(), krlmlr(), andrie1()) 

这些是我得到的结果:

 Unit: microseconds expr min lq mean median uq max neval lilip() 194.562 373.7335 772.5663 889.7045 950.4035 1611.537 100 krlmlr() 226270.845 237985.6560 260194.9269 251581.0235 280704.2320 373022.180 100 andrie1() 87916.021 90437.4820 92791.8923 92636.8420 94448.7040 102543.252 100 

但是我不知道为什么我的krlmlr()andrie1()比MichaelChirico的例子performance得差得多。 任何线索?

 try this~ data_format <- function(data,digit=2,type='%'){ if(type=='d') { type = 'f'; digit = 0; } switch(type, '%' = {format <- paste("%.", digit, "f%", type, sep='');num <- 100}, 'f' = {format <- paste("%.", digit, type, sep='');num <- 1}, cat(type, "is not a recognized type\n") ) sprintf(format, num * data) } 

这个函数可以将数据按列转换成百分比

 percent.colmns = function(base, columnas = 1:ncol(base), filas = 1:nrow(base)){ base2 = base for(j in columnas){ suma.c = sum(base[,j]) for(i in filas){ base2[i,j] = base[i,j]*100/suma.c } } return(base2) }