Python Format Tabular Output

Python format tabular output

It's not really hard to roll your own formatting function:

def print_table(table):
col_width = [max(len(x) for x in col) for col in zip(*table)]
for line in table:
print "| " + " | ".join("{:{}}".format(x, col_width[i])
for i, x in enumerate(line)) + " |"

table = [(str(x), str(f(x))) for x in mylist]
print_table(table)

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.

Python: Flexible way to format string output into a table without using a non-standard library

There are not many ways. To be able to know the column width, you first need to read your data and to calculate the appropriate width per column.

Only then you can generate the table.

Here is a naive implementation:

def mktable(dic, header=None):
# get max col width
col_widths = list(map(max, zip(*(map(lambda x: len(str(x)), (k,*v))
for k,v in dic.items()))))

# default numeric header if missing
if not header:
header = range(1, len(col_widths)+1)

header_widths = map(lambda x: len(str(x)), header)

# correct column width if headers are longer
col_widths = [max(c,h) for c,h in zip(col_widths, header_widths)]

# create separator line
line = '+%s+' % '+'.join('-'*(w+2) for w in col_widths)
#line = '-' * (sum(col_widths)+(len(col_widths)-1)*3+4)

# create formating string
fmt_str = '| %s |' % ' | '.join(f'{{:<{i}}}' for i in col_widths)

# header
print(line)
print(fmt_str.format(*header))
print(line)

# data
for k, v in countries_dict.items():
print(fmt_str.format(k, *v))

# footer
print(line)
mktable(countries_dict, header=('Country', 'Capital', '----- Area -----'))

output:

+---------------+------------------+------------------+
| Country | Capital | ----- Area ----- |
+---------------+------------------+------------------+
| Russia | Moscow | 17098246 |
| Canada | Ottawa | 9984670 |
| China | Beijing | 9596961 |
| United States | Washington, D.C. | 9525067 |
| Brazil | Brasília | 8515767 |
+---------------+------------------+------------------+

How to format a text file into even tabular format?

Loop through the data once, to discover the maximum width of each column:

with open('quest_load.txt', 'r') as f:
for i, line in enumerate(f):
if i == 0:
max_widths = [len(col) for col in line.split('|')]
continue
max_widths = [
max(len(col), curr_max)
for col, curr_max in zip(line.split('|'), max_widths)
]

Then loop again to print the columns, formatting each column according to max width:

with open('quest_load.txt', 'r') as f:
for line in f:
content = line.split('|')
formatted = [
f'{substr: <{width}}'
for substr, width in zip(content, max_widths)
]
print('\t'.join(formatted), end='')

Output:

capital     What is the capital of Egypt?   Cairo       3
pi What is pi to two digits? 3.14 3
dozen How many eggs in a dozen? 12 1
president Who was the first president? Washington 1

Create nice column output in python

data = [['a', 'b', 'c'], ['Python Format Tabular Outputaa', '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
Python Format Tabular Outputaa 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.

Pretty printing a list in a tabular format

mylist = [ ( ('12', '47', '4', '574862', '58', '7856'), 'AGGREGATE_VALUE1'),
( ('2', '75', '757', '8233', '838', '47775272785'), 'AGGREG2'),
( ('4144', '78', '78965', '778', '78578', '2'), 'AGGREGATE_VALUE3')]

longg = dict.fromkeys((0,1,2,3,4,5,6),0)

for tu,x in mylist:
for i,el in enumerate(tu):
longg[i] = max(longg[i],len(str(el)))
longg[6] = max(longg[6],len(str(x)))

fofo = ' '.join('%'+str(longg[i])+'s' for i in xrange(0,7))
print '\n'.join(fofo % (a,b,c,d,e,f,g) for (a,b,c,d,e,f),g in mylist)

result

  12  47      4  574862     58         7856  AGGREGATE_VALUE1
2 75 757 8233 838 47775272785 AGGREG2
4144 78 78965 778 78578 2 AGGREGATE_VALUE3

Don't know if this fills your need

EDIT 1

Using string formatting with modulo operator (%) to print in a constant length, '%6s' right-justifies in a constant length of 6, and '%-6s' left-justifies in a constant length of 6.

You'll find precisions here

But there is no sense to specify a constant length to print something at the end of a string, because it's somewhat naturally-left-justified in this case.
Then :

longg = dict.fromkeys((0,1,2,3,4,5,),0)

for tu,x in mylist:
for i,el in enumerate(tu):
longg[i] = max(longg[i],len(str(el)))

fofo = ' '.join('%'+str(longg[i])+'s' for i in xrange(0,6)) + ' %s'
print '\n'.join(fofo % (a,b,c,d,e,f,g) for (a,b,c,d,e,f),g in mylist)

EDIT 2

mylist = [ ( (12, 47, 4, 574862, 58, 7856), 'AGGREGATE_VALUE1'),
( (2, 75, 757, 8233, 838, 47775272785), 'AGGREG2'),
( (4144, 78, 78965, 778, 78578, 2), 'AGGREGATE_VALUE3')]

longg = dict.fromkeys((0,1,2,3,4,5),0)

for tu,_ in mylist:
longg.update(( i, max(longg[i],len(str(el))) ) for i,el in enumerate(tu))

fofo = ' '.join('%%%ss' % longg[i] for i in xrange(0,6)) + ' %s'
print '\n'.join(fofo % (a,b,c,d,e,f,g) for (a,b,c,d,e,f),g in mylist)

EDIT 3

mylist = [ ( (12, 47, 4, 574862, 58, 7856), 'AGGREGATE_VALUE1'),
( (2, 75, 757, 8233, 838, 47775272785), 'AGGREG2'),
( (4144, 78, 78965, 778, 78578, 2), 'AGGREGATE_VALUE3')]

header = ('Price1','Price2','reference','XYD','code','resp','AGGREG values')

longg = dict(zip((0,1,2,3,4,5,6),(len(str(x)) for x in header)))

for tu,x in mylist:
longg.update(( i, max(longg[i],len(str(el))) ) for i,el in enumerate(tu))
longg[6] = max(longg[6],len(str(x)))
fofo = ' | '.join('%%-%ss' % longg[i] for i in xrange(0,7))

print '\n'.join((fofo % header,
'-|-'.join( longg[i]*'-' for i in xrange(7)),
'\n'.join(fofo % (a,b,c,d,e,f,g) for (a,b,c,d,e,f),g in mylist)))

result

Price1 | Price2 | reference | XYD    | code  | resp        | AGGREG values   
-------|--------|-----------|--------|-------|-------------|-----------------
12 | 47 | 4 | 574862 | 58 | 7856 | AGGREGATE_VALUE1
2 | 75 | 757 | 8233 | 838 | 47775272785 | AGGREG2
4144 | 78 | 78965 | 778 | 78578 | 2 | AGGREGATE_VALUE3

Note that this kind of formatting would be much easier with the string's method format() introduced in Python 2.6



Related Topics



Leave a reply



Submit