Incorrect Column Alignment When Printing Table in Python Using Tab Characters

Incorrect column alignment when printing table in Python using tab characters

One possible solution is to rely on some package that has been designed for this purpose, like tabulate: Read more about it!

Keep in mind that you have to install this using e.g. pip install tabulate

from tabulate import tabulate

print tabulate([[00, 00, 00], [00, 00, 00], [00, 00, 00]], headers=['X Coordinate','Y Coordinate','Result'], tablefmt='orgtbl')

Or use your original table with this code:

alignment = len(max(table.split("\t")))+1

for line in table.strip().split("\n"):
row ="{{:>{}}}".format(alignment) * len(line.strip().split("\t"))
print row.format(*line.strip().split("\t"))

Why does \t in python make output automatically align to the left?

That's how it's supposed to work.

A tab character, when printed to a terminal, becomes enough spaces to space up to the next multiple of 8*. (This makes it useful for making tables.)

So if you print pairs of numbers separated by tabs, you get:

        | <-- 8 characters is here
1 23456
12 3456
123 456
1234 56

etc. But you can't see this effect when you're using them to indent, because when there's nothing in front of them they all come out full width, so you get:

        | <-- 8 characters is here
non-indented stuff
indented stuff

* Tab size is configurable in many text editors, but generally not in terminals, where you get the traditional default of 8.

Line up columns of numbers (print output in table format)

Here is a simple, self-contained example that shows how to format variable column widths:

data = '''\
234 127 34 23 45567
23 12 4 4 45
23456 2 1 444 567'''

# Split input data by row and then on spaces
rows = [ line.strip().split(' ') for line in data.split('\n') ]

# Reorganize data by columns
cols = zip(*rows)

# Compute column widths by taking maximum length of values per column
col_widths = [ max(len(value) for value in col) for col in cols ]

# Create a suitable format string
format = ' '.join(['%%%ds' % width for width in col_widths ])

# Print each row using the computed format
for row in rows:
print format % tuple(row)

which outputs:

  234 127 34  23 45567
23 12 4 4 45
23456 2 1 444 567

How to realize a table with a specific elements subset

Since you use tabulate, there is a solution to modify your code by:

  1. Adding an extra row full of characters of specified size for each column at the end the array
  2. Calling tabulate including specification of the alignment using coalign
  3. Remove the extra row

Since the output is a string, the width of the columns is not associated with any measure e.g. in cm, so you will need to define a length scale that suits your needs, i.e. the number of characters per required width unit.

Note that 2 characters are removed from the computed width to account for the inner column margins which are 1 character left and right.

from tabulate import tabulate

pt = [(1,"Hydrogen","H",1.008), (2,"Helium","He",4.0026), (3, "Lithium", "Li", 6.94), (4, "Beryllium", "Be", 9.0122),
(5, "Boron", "B", 10.81), (6, "Carbon", "C", 12.011), (7, "Nitrogen", "N", 14.007), (8, "Oxygen", "O", 15.999),
(9, "Fluorine", "F", 18.998), (10, "Neon", "Ne", 20.180)]
head = ["No.", "Name", "Symbol", "Weight"]

lengthScale = 2
widths = [3, 20, 6, 10]
pt.append(["-"*(width*lengthScale-2) for width in widths])

tab = tabulate(pt, headers=head, tablefmt="grid", colalign=("right","left","center","right"))

for line in range(2):
tab = tab[:tab.rfind('\n')]

print(tab)

It produces:

+-------+----------------------------------------+------------+--------------------+
| No. | Name | Symbol | Weight |
+=======+========================================+============+====================+
| 1 | Hydrogen | H | 1.008 |
+-------+----------------------------------------+------------+--------------------+
| 2 | Helium | He | 4.0026 |
+-------+----------------------------------------+------------+--------------------+
| 3 | Lithium | Li | 6.94 |
+-------+----------------------------------------+------------+--------------------+
| 4 | Beryllium | Be | 9.0122 |
+-------+----------------------------------------+------------+--------------------+
| 5 | Boron | B | 10.81 |
+-------+----------------------------------------+------------+--------------------+
| 6 | Carbon | C | 12.011 |
+-------+----------------------------------------+------------+--------------------+
| 7 | Nitrogen | N | 14.007 |
+-------+----------------------------------------+------------+--------------------+
| 8 | Oxygen | O | 15.999 |
+-------+----------------------------------------+------------+--------------------+
| 9 | Fluorine | F | 18.998 |
+-------+----------------------------------------+------------+--------------------+
| 10 | Neon | Ne | 20.18 |
+-------+----------------------------------------+------------+--------------------+

Replace tab with variable amount of spaces, maintaining the alignment

The POSIX utility pr called as pr -e -t does exactly what you want and AFAIK is present in every Unix installation.

$ cat file
ABC 1437 1 0 71 15.7 174.4
DEF 0 0 0 1 45.9 45.9
GHIJ 2 3 0 9 1.1 1.6

$ pr -e -t file
ABC 1437 1 0 71 15.7 174.4
DEF 0 0 0 1 45.9 45.9
GHIJ 2 3 0 9 1.1 1.6

and with the tabs visible as ^Is:

$ cat -ET file
ABC^I1437^I1^I0^I71^I15.7^I174.4$
DEF^I0^I0^I0^I1^I45.9^I45.9$
GHIJ^I2^I3^I0^I9^I1.1^I1.6$

$ pr -e -t file | cat -ET
ABC 1437 1 0 71 15.7 174.4$
DEF 0 0 0 1 45.9 45.9$
GHIJ 2 3 0 9 1.1 1.6$

Printing Lists as Tabular Data

Some ad-hoc code:

row_format ="{:>15}" * (len(teams_list) + 1)
print(row_format.format("", *teams_list))
for team, row in zip(teams_list, data):
print(row_format.format(team, *row))

This relies on str.format() and the Format Specification Mini-Language.

Create nice column output in python

data = [['a', 'b', 'c'], ['Incorrect Column Alignment When Printing Table in Python Using Tab Charactersaa', 'b', 'c'], ['a', 'bb', 'c']]

col_width = max(len(word) for row in data for word in row) + 2 # padding
for row in data:
print "".join(word.ljust(col_width) for word in row)

a b c
Incorrect Column Alignment When Printing Table in Python Using Tab Charactersaa b c
a bb c

What this does is calculate the longest data entry to determine the column width, then use .ljust() to add the necessary padding when printing out each column.



Related Topics



Leave a reply



Submit