Skip to content

Instantly share code, notes, and snippets.

@sadikovi
Created June 10, 2017 04:55
Show Gist options
  • Save sadikovi/8a2b9a472729f17f387cb53ffbdcbee6 to your computer and use it in GitHub Desktop.
Save sadikovi/8a2b9a472729f17f387cb53ffbdcbee6 to your computer and use it in GitHub Desktop.
Display table nicely in Python with margin and projection (table is a list of dictionary rows)
################################################################
# Example
################################################################
print("\n# Empty rows list")
show([])
print("\n# Rows list with inconsistent set of columns and margin of 4 spaces")
rows = [
{"col1": 1, "col2": 2.1, "col3": "long text", "col4": "", "col5": True},
{"col1": 2, "col2": 3.2, "col3": "def"},
{"col1": 3, "col2": 4.3334, "col3": "ghi", "col4": None}
]
show(rows, margin=4)
print("\n# Rows with different value types and enforced column order")
rows = [
{"sdate": "2015-01-01", "min": 1.0234, "max": 3935.234, "mean": 1.2, "std": "NaN"},
{"sdate": "2015-01-02", "min": 1.234, "max": 234.2, "mean": 34.2, "std": "NaN"},
{"sdate": "2015-01-03", "min": 1.0, "max": 3.8, "mean": 2.3, "std": "NaN"},
{"sdate": "2015-01-04", "min": 2.04, "max": 810.34, "mean": 789.32, "std": "NaN"},
{"sdate": "2015-01-05", "min": "NaN", "max": "NaN", "mean": 0.001, "std": "NaN"}
]
show(rows, columns=["sdate", "min", "max", "mean", "std"])
show(rows, margin=4, columns=["sdate", "mean"])
"""
# Empty rows list
++
||
++
++
# Rows list with inconsistent set of columns and margin of 4 spaces
+-----+-----+-------+----------+-----+
| col4| col5| col2| col3| col1|
+-----+-----+-------+----------+-----+
| | True| 2.1| long text| 1|
| | | 3.2| def| 2|
| None| | 4.3334| ghi| 3|
+-----+-----+-------+----------+-----+
# Rows with different value types and enforced column order
+-----------+-------+---------+-------+----+
| sdate| min| max| mean| std|
+-----------+-------+---------+-------+----+
| 2015-01-01| 1.0234| 3935.234| 1.2| NaN|
| 2015-01-02| 1.234| 234.2| 34.2| NaN|
| 2015-01-03| 1.0| 3.8| 2.3| NaN|
| 2015-01-04| 2.04| 810.34| 789.32| NaN|
| 2015-01-05| NaN| NaN| 0.001| NaN|
+-----------+-------+---------+-------+----+
+-----------+-------+
| sdate| mean|
+-----------+-------+
| 2015-01-01| 1.2|
| 2015-01-02| 34.2|
| 2015-01-03| 2.3|
| 2015-01-04| 789.32|
| 2015-01-05| 0.001|
+-----------+-------+
"""
#!/usr/bin/python
def table(rows, margin=0, columns=[]):
"""
Return string representing table content, returns table as string and as a list of strings.
It is okay for rows to have different sets of keys, table will show union of columns with
missing values being empty spaces.
:param rows: list of dictionaries as rows
:param margin: left space padding to apply to each row, default is 0
:param columns: extract listed columns in provided order, other columns will be ignored
:return: table content as string and as list
"""
def projection(cols, columns):
return [(x, cols[x]) for x in columns if x in cols] if columns else cols.items()
def row_to_string(row, columns):
values = [(row[name] if name in row else "").rjust(size) for name, size in columns]
return "|%s|" % ("|".join(values))
def header(columns):
return "|%s|" % ("|".join([name.rjust(size) for name, size in columns]))
def divisor(columns):
return "+%s+" % ("+".join(["-" * size for name, size in columns]))
data = [dict([(str(a), str(b)) for a, b in row.items()]) for row in rows]
cols = dict([(x, len(x) + 1) for row in data for x in row.keys()]) if data else {}
for row in data:
for key in row.keys():
cols[key] = max(cols[key], len(row[key]) + 1)
proj = projection(cols, columns) # extract certain columns to display (or all if not provided)
table = [divisor(proj), header(proj), divisor(proj)] + \
[row_to_string(row, proj) for row in data] + [divisor(proj)]
table = ["%s%s" % (" " * margin, tpl) for tpl in table] if margin > 0 else table
table_text = "\n".join(table)
return (table_text, table)
def show(rows, margin=0, columns=[]):
"""
Print table in console for list of rows.
"""
txt, _ = table(rows, margin, columns)
print(txt)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment