Skip to content

Commit 3a0734c

Browse files
committed
Added special code to deal with Pandas DataFrames and NumPy RecordArrays
Also: - Added data_types.py example TODO: - Updated README.md - Add unit tests
1 parent 2b2c9d8 commit 3a0734c

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed

examples/data_types.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#!/usr/bin/env python
2+
# coding=utf-8
3+
"""
4+
tableformatter supports and has been tested with the following tabular data types:
5+
- lists of lists or other iterables of iterables
6+
- two-dimensional NumPy array
7+
- list or another iterable of dicts (dict keys iterated through as column values)
8+
- dict of iterables (dict keys iterated through as rows where each key must be a hashable iterable)
9+
- NumPy record arrays (names as columns)
10+
- pandas.DataFrame
11+
- list or another iterable of arbitrary non-iterable objects (column specifier required)
12+
13+
This example demonstrates tableformatter working with these data types in the simplest possible manner.
14+
"""
15+
import numpy as np
16+
import pandas as pd
17+
import tableformatter as tf
18+
19+
iteralbe_of_iterables = [[1, 2, 3, 4],
20+
[5, 6, 7, 8]]
21+
print("Data type: iterable of iterables")
22+
print(iteralbe_of_iterables)
23+
print(tf.generate_table(iteralbe_of_iterables))
24+
25+
np_2d_array = np.array([[1, 2, 3, 4],
26+
[5, 6, 7, 8]])
27+
print("Data type: NumPy 2D array")
28+
print(np_2d_array)
29+
print(tf.generate_table(np_2d_array))
30+
31+
np_rec_array = np.rec.array([(1, 2., 'Hello'),
32+
(2, 3., "World")],
33+
dtype=[('foo', 'i4'), ('bar', 'f4'), ('baz', 'U10')])
34+
print("Data type: Numpy record array")
35+
print(np_rec_array)
36+
print(tf.generate_table(np_rec_array))
37+
38+
d = {'col1': [1, 5], 'col2': [2, 6], 'col3': [3, 7], 'col4': [4, 8]}
39+
pandas_dataframe = pd.DataFrame(data=d)
40+
print("Data type: Pandas DataFrame")
41+
print(pandas_dataframe)
42+
print(tf.generate_table(pandas_dataframe))
43+
44+
iterable_of_dicts = [ {1: 'a', 2: 'b', 3: 'c', 4: 'd'},
45+
{5: 'e', 6: 'f', 7: 'g', 8: 'h'}]
46+
print("Data type: iterable of dicts (dict keys iterated through as column values)")
47+
print(iterable_of_dicts)
48+
print(tf.generate_table(iterable_of_dicts))
49+
50+
dict_of_iterables = {(1, 2, 3, 4): 'a',
51+
(5, 6, 7, 8): 'b'}
52+
print("Data type: dict of iterables (dict keys iterated through as rows where each key must be a hashable iterable)")
53+
print(dict_of_iterables)
54+
print(tf.generate_table(dict_of_iterables))
55+
56+
57+
class MyRowObject(object):
58+
"""Simple object to demonstrate using a list of non-iterable objects with TableFormatter"""
59+
def __init__(self, field1: int, field2: int, field3: int, field4: int):
60+
self.field1 = field1
61+
self.field2 = field2
62+
self._field3 = field3
63+
self.field4 = field4
64+
65+
def get_field3(self):
66+
"""Demonstrates accessing object functions"""
67+
return self._field3
68+
69+
70+
rows = [MyRowObject(1, 2, 3, 4),
71+
MyRowObject(5, 6, 7, 8)]
72+
columns = (tf.Column('Col1', attrib='field1'),
73+
tf.Column('Col2', attrib='field2'),
74+
tf.Column('Col3', attrib='get_field3'),
75+
tf.Column('Col4', attrib='field4'))
76+
print("Data type: iterable of arbitrary non-iterable objects")
77+
print(rows)
78+
print(tf.generate_table(rows, columns))

tableformatter.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,27 @@ def generate_table(rows: Iterable[Union[Iterable, object]],
615615
:param row_tagger: decorator function to apply per-row options
616616
:return: formatted string containing the table
617617
"""
618+
# Extract column headers if this is a NumPy record array and columns weren't specified
619+
if not columns:
620+
try:
621+
import numpy as np
622+
except ImportError:
623+
pass
624+
else:
625+
if isinstance(rows, np.recarray):
626+
columns = rows.dtype.names
627+
628+
# Deal with Pandas DataFrames not being iterable in a sane way
629+
try:
630+
import pandas as pd
631+
except ImportError:
632+
pass
633+
else:
634+
if isinstance(rows, pd.DataFrame):
635+
if not columns:
636+
columns = rows.columns
637+
rows = rows.values
638+
618639
show_headers = True
619640
use_attrib = False
620641
if isinstance(columns, Collection) and len(columns) > 0:

0 commit comments

Comments
 (0)