11.4 Formatted Printing

Quite often when we are printing out to the console we want each line to follow some uniform format. This can be accomplished with the sprintf() function.28 Lets begin with an example:

first <- "Mary"
last <- "Poppins"
sprintf(fmt = "%10s%20s", first, last)
## [1] "      Mary             Poppins"

sprintf() builds a string from the strings first and last that were passed to it. The fmt parameter is a string that encodes the format of the result. In this example, the command comes down to:

  • create a string of width 10, consisting of five spaces followed by the five characters of “Mary”
  • create a string of width 20, consisting of 13 spaces followed by the seven characters of “Poppins”
  • The preceding two strings are called fields. We then join the above the fields, with nothing between them.

Here is the result, cated out:

sprintf(fmt = "%10s%20s", first, last) %>% 
  cat()
##       Mary             Poppins

The “s” in the the fmt argument is called a conversion character. It tells sprintf() to expect a string. Each percent sign indicates the beginning of a new field. For each field, the desired field-width should appear between the percent-sign and the conversion character for the field.

In the text above, the names are right-justified, meaning that they appear at the end of their respective fields. If you want a field to be left-justified, insert a hyphen anywhere between the percent sign and the conversion character, like so:

# left-justify both fields:
sprintf(fmt = "%-10s%-20s", first, last) %>% cat()
## Mary      Poppins

Other common conversion characters are:

  • d: an integer
  • f: a decimal number (default is 6 digits precision)
  • g: a decimal number where the default precision is determined by the number of significant figures in the given number

Here is another example:

sprintf(fmt = "%-10s%-10d%-10f", "Mary", 1955, 3.2) %>% cat()
## Mary      1955      3.200000

The following example is the same as above, except that we retain only the significant figures in the 3.2:

sprintf(fmt = "%-10s%-10d%-10g", "Mary", 1955, 3.2) %>% cat()
## Mary      1955      3.2

When you are creating a field for a decimal number, you can specify both the total field-width and the precision together if you separate them with a .. Thus, if you want the number 234.5647 to appear right-justified in a field of width 10, showing only the first three decimal places, then try:

sprintf(fmt = "%-10s%-10d%-10.3f", "Mary", 1955, 234.5647) %>% 
  cat()
## Mary      1955      234.565

sprintf() comes in handy when you want your output to appear in nicely-aligned, tabular fashion. Consider this example:

# information for three people:
firstName <- c("Donald", "Gina", "Rohini")
lastName <- c("Duck", "Gentorious", "Lancaster")
age <- c(17, 19, 20)
gpa <- c(3.7, 3.9, 3.823)
for (i in 1:3) {
  sprintf("%-15s%-20s%-5d%-5.2f\n", 
          firstName[i], lastName[i], age[i], gpa[i]) %>% 
    cat()
}
## Donald         Duck                17   3.70 
## Gina           Gentorious          19   3.90 
## Rohini         Lancaster           20   3.82

Note the use of “\n” in the fmt argument to ensure that the output appears on separate lines.

You could take advantage of vectorization to avoid the loop:

sprintf("%-15s%-20s%5-d%-5.2f\n", 
        firstName, lastName, age, gpa) %>% 
  cat()
## Donald         Duck                17   3.70 
##  Gina           Gentorious          19   3.90 
##  Rohini         Lancaster           20   3.82

Well, that’s not quite right: the second and third lines begin with a space. This happens because cat() separates its input with a space by default. You can prevent this, however, with the sep parameter of cat():

sprintf("%-15s%-20s%-5d%-5.2f\n", 
        firstName, lastName, age, gpa) %>% 
  cat(sep = "")
## Donald         Duck                17   3.70 
## Gina           Gentorious          19   3.90 
## Rohini         Lancaster           20   3.82

  1. You can think of sprintf as short for: “formatted printing in S.” S was the forerunner to the R language.↩︎