Take control of your Python print() statements: part 3

In the last post, we learned how to control the precision of the number we print as well as the number of spaces these numbers take up. The last thing we need to learn to output nice data tables is how to align text and numbers when we use .format().

Aligning text and numbers with .format()

We previously learned to specify the number of spaces allocated to the inputs we provide to .format(). Now we will see that we can tell Python how we want to align our text or numbers in these spaces. We can left-adjust (<), right-adjust (>) and center (^) our values. Here is a brief example:

# Example 1
print('L {:<20} R'.format('x'))
# Example 2
print('L {:^20} R'.format('x'))
# Example 3
print('L {:>20} R'.format('x'))

The output of these examples is:

L x                    R
L          x           R
L                    x R

Pretty cool. We told Python to leave 20 spaces for the text we wanted to enter, and depending on the symbol we specified, we were able to change the justification of our text.

You can even specify the character you want to use instead of empty spaces.

print ('{:=<20}'.format('hello'))
print ('{:_^20}'.format('hello'))
print ('{:.>20}'.format('hello'))

The output of these example is:

hello===============
_______hello________
...............hello

As you can see, .format() has lots of options. Visit the string documentation or this useful site if you want to learn more.

Putting it all together

When working with data, we often want to have a quick look to make sure there are no mistakes and to see if any patterns are present. One way to do this is to plot your data. However, some types of data tend to be better presented in a nicely structured table.

For this example, we will work with some made-up data:

data = [['NAME', 'AGE', 'HANDEDNESS', 'SCORE (%)'],
        ['Martin', 38, 'L', 54.123],
        ['Marty', 33, 'L', 32.438],
        ['Martine', 25, 'R', 71.128],
        ['Martyn', 59, 'R', 50.472],
        ['Mart', 23, 'L', 2.438],
        ['Martyne', 15, 'R', 71.128],
        ['Marlyn', 101, 'R', 0.472],
        ['Marti', 2, 'L', 55.438],
        ['Mardi', 9, 'R', 81.128],
        ['Martyne', 49, 'R', 24.472],
        ['Marteen', 91, 'L', 1.128]]

Note that the first row of data (data[0]) contains the column labels. The other rows contain the data for each subject.

As you might suspect, running print(data) does not result in a nice output (try it to see for yourself!). A better solution is to apply what we have learned to generate a nice table. Here is the code:

dash = '-' * 40

for i in range(len(data)):
    if i == 0:
      print(dash)
      print('{:<10s}{:>4s}{:>12s}{:>12s}'.format(data[i][0],data[i][1],data[i][2],data[i][3]))
      print(dash)
    else:
      print('{:<10s}{:>4d}{:^12s}{:>12.1f}'.format(data[i][0],data[i][1],data[i][2],data[i][3]))

The output of this code look like this:

----------------------------------------
NAME       AGE  HANDEDNESS   SCORE (%)
----------------------------------------
Martin      38     L              54.1
Marty       33     L              32.4
Martine     25     R              71.1
Martyn      59     R              50.5
Mart        23     L               2.4
Martyne     15     R              71.1
Marlyn     101     R               0.5
Marti        2     L              55.4
Mardi        9     R              81.1
Martyne     49     R              24.5
Marteen     91     L               1.1

In terms of the code, we first create a variable called dash that contains 40 dashes.

The code then looped over each of the 12 items in our data variable. If we are dealing with our first item (i.e., i = 0), we tell Python that we want to print a line of dashes, then print our headers, followed by another line of dashes. Notice how we specify the number of spaces we want for each header as well as the alignment of the text.

For all the other items in our data variable, we print the text and values using the same number of spaces used for the header, and specify whether we want to print integers (d), a strings (s) or floating point numbers (f). Note that because HANDEDNESS is such a long word, it looks better to center the text printed below it. Otherwise, the alignment is the same as for the header row.

Make sure you understand how this code works. To really consolidate your learning, try changing things in the print statements and see if it generates the expected outcome.

Conclusion

Hopefully you enjoyed these tutorials on the .format() string method and the print() function. Now you have no more excuses for ugly and uninformative print statements!

And if you want more readable Python print statements, consider using f-strings. As I discuss in this post, they are the modern way to print text in Python.

13 comments

  • Very nice article. Easy to follow and very instructive. Thank you.

    Like

  • How can I create a table like the last one as an output of a function?

    Like

    • from collections import namedtuple
      
      
      def print_table(decimal=2):
          """Function that return text to plot in table format
      
          decimal: int
              Specify number of decimal points to include for data in table
          """
      
          # Create table header
          header = ("outcome", "mean", "95 CI")
          header_filled = f"{header[0]:<12s}{header[1]:>16s}{header[2]:^34s}"
          markers = "-" * len(header_filled)
          header = [markers, header_filled, markers]
      
          # Create simulated data to include in table
          names = ['baseline', 'post_10min', 'post_20min']
          Estimate = namedtuple('Estimates', ('mean', 'ci')) # namedtuples are great!
          baseline = Estimate(mean=25.4435657, ci= (24.122346, 26.845673))
          post_10min = Estimate(mean=21.5421192, ci= (19.1456789, 24.85657845))
          post_20min = Estimate(mean=27.334554956, ci= (25.534345465, 30.6167956))
          estimates = (baseline, post_10min, post_20min)
      
          # Create rows of data to be included in table
          results = list()
          for estimate, name in zip(estimates, names):
              results.append(
                      f"{name:<12s}{estimate.mean:>16.{decimal}f}{estimate.ci[0]:>15.{decimal}f}"
                      f" to {estimate.ci[1]:<15.{decimal}f}"
                  )
          # return everything as a string, joined by newlines (i.e. \n)
          return "\n".join(header + results + [markers])
      
      print(print_table())
      

      This above code creates the following table:

      --------------------------------------------------------------
      outcome                 mean              95 CI               
      --------------------------------------------------------------
      baseline               25.44          24.12 to 26.85          
      post_10min             21.54          19.15 to 24.86          
      post_20min             27.33          25.53 to 30.62          
      --------------------------------------------------------------
      

      Like

  • helpful! thanks.

    Like

  • Adam Wróblewski

    Can i input int variable into {:<10s} instead of 10?

    Like

    • You can, but means of another format variable:

      for example:

      x = 10.3
      y = 5.5555555555
      print(“{0:>{1}f}”.format(y ,x))
      5.5556

      Or for a string:
      x = 40
      y = ‘me and you’
      print(“{0:>{1}s}”.format(y,x))
      me and you

      Like

      • This is exactly what I was going to ask! Thx for the article Martin, and for the question, Adam. Both super helpful.

        Like

  • To print continuous line in Python: print(‘\u2014’*30)
    That’s Unicode Character ‘EM DASH’ printed 30 times.
    About the character: https://www.fileformat.info/info/unicode/char/2014/index.htm
    https://en.wikipedia.org/wiki/List_of_Unicode_characters

    Like

  • Hi Martin, do you know how to draw a continuous line using print function in Python? I tried with ‘_’ but need a rigid line.

    Like

    • Hi Mary, I don’t think there is a way (or an at least an easy way) to make a continuous line with the print function. This is because the print function is for text, or ASCII characters. A continuous line, like the ones you might be able to make in LibreOffice or Microsoft Word, are not simple text characters. Please do let us know if you figure out how to do it!

      Like

  • Thank you Martin. I could solve my problem!!!

    Like

  • Thank you so much, it’s really helpful!

    Like

Leave a comment