How to format a number as percentage in R?
Check out the scales
package. It used to be a part of ggplot2
, I think.
library('scales')
percent((1:10) / 100)
# [1] "1%" "2%" "3%" "4%" "5%" "6%" "7%" "8%" "9%" "10%"
The built-in logic for detecting the precision should work well enough for most cases.
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%"
Check out the percent
function from the formattable
package:
library(formattable)
x <- c(0.23, 0.95, 0.3)
percent(x)
[1] 23.00% 95.00% 30.00%
Even later:
As pointed out by @DzimitryM, percent()
has been "retired" in favor of label_percent()
, which is a synonym for the old percent_format()
function.
label_percent()
returns a function, so to use it, you need an extra pair of parentheses.
library(scales)
x <- c(-1, 0, 0.1, 0.555555, 1, 100)
label_percent()(x)
## [1] "-100%" "0%" "10%" "56%" "100%" "10 000%"
Customize this by adding arguments inside the first set of parentheses.
label_percent(big.mark = ",", suffix = " percent")(x)
## [1] "-100 percent" "0 percent" "10 percent"
## [4] "56 percent" "100 percent" "10,000 percent"
An update, several years later:
These days there is a percent
function in the scales
package, as documented in krlmlr's answer. Use that instead of my hand-rolled solution.
Try something like
percent <- function(x, digits = 2, format = "f", ...) {
paste0(formatC(100 * x, format = format, digits = digits, ...), "%")
}
With usage, e.g.,
x <- c(-1, 0, 0.1, 0.555555, 1, 100)
percent(x)
(If you prefer, change the format from "f"
to "g"
.)
Base R
I much prefer to use sprintf
which is available in base R.
sprintf("%0.1f%%", .7293827 * 100)
[1] "72.9%"
I especially like sprintf
because you can also insert strings.
sprintf("People who prefer %s over %s: %0.4f%%",
"Coke Classic",
"New Coke",
.999999 * 100)
[1] "People who prefer Coke Classic over New Coke: 99.9999%"
It's especially useful to use sprintf
with things like database configurations; you just read in a yaml file, then use sprintf to populate a template without a bunch of nasty paste0
's.
Longer motivating example
This pattern is especially useful for rmarkdown reports, when you have a lot of text and a lot of values to aggregate.
Setup / aggregation:
library(data.table) ## for aggregate
approval <- data.table(year = trunc(time(presidents)),
pct = as.numeric(presidents) / 100,
president = c(rep("Truman", 32),
rep("Eisenhower", 32),
rep("Kennedy", 12),
rep("Johnson", 20),
rep("Nixon", 24)))
approval_agg <- approval[i = TRUE,
j = .(ave_approval = mean(pct, na.rm=T)),
by = president]
approval_agg
# president ave_approval
# 1: Truman 0.4700000
# 2: Eisenhower 0.6484375
# 3: Kennedy 0.7075000
# 4: Johnson 0.5550000
# 5: Nixon 0.4859091
Using sprintf
with vectors of text and numbers, outputting to cat
just for newlines.
approval_agg[, sprintf("%s approval rating: %0.1f%%",
president,
ave_approval * 100)] %>%
cat(., sep = "\n")
#
# Truman approval rating: 47.0%
# Eisenhower approval rating: 64.8%
# Kennedy approval rating: 70.8%
# Johnson approval rating: 55.5%
# Nixon approval rating: 48.6%
Finally, for my own selfish reference, since we're talking about formatting, this is how I do commas with base R:
30298.78 %>% round %>% prettyNum(big.mark = ",")
[1] "30,299"