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"

Tags:

Formatting

R