Skip to content

Commit d0c7090

Browse files
committed
pandas.plotting now supports table keywords
1 parent 516c0c7 commit d0c7090

File tree

5 files changed

+142
-2
lines changed

5 files changed

+142
-2
lines changed

doc/source/release.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,17 @@ API Changes
161161

162162
- Added ``nunique`` and ``value_counts`` functions to ``Index`` for counting unique elements. (:issue:`6734`)
163163

164+
- ``DataFrame.plot`` and ``Series.plot`` now support a ``table`` keyword for plotting ``matplotlib.Table``. The ``table`` kewyword can receive the following values.
165+
166+
- ``False``: Do nothing (default).
167+
168+
- ``True``: Draw a table using the ``DataFrame`` or ``Series`` called ``plot`` method. Data will be transposed to meet matplotlib's default layout.
169+
170+
- ``DataFrame`` or ``Series``: Draw matplotlib.table using the passed data. The data will be drawn as displayed in print method (not transposed automatically).
171+
172+
Also, helper function ``pandas.tools.plotting.table`` is added to create a table from ``DataFrame`` and ``Series``, and add it to an ``matplotlib.Axes``.
173+
174+
164175
Deprecations
165176
~~~~~~~~~~~~
166177

doc/source/v0.14.0.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,17 @@ API changes
201201

202202
- Added ``nunique`` and ``value_counts`` functions to ``Index`` for counting unique elements. (:issue:`6734`)
203203

204+
- ``DataFrame.plot`` and ``Series.plot`` now support a ``table`` keyword for plotting ``matplotlib.Table``. The ``table`` kewyword can receive the following values.
205+
206+
- ``False``: Do nothing (default).
207+
208+
- ``True``: Draw a table using the ``DataFrame`` or ``Series`` called ``plot`` method. Data will be transposed to meet matplotlib's default layout.
209+
210+
- ``DataFrame`` or ``Series``: Draw matplotlib.table using the passed data. The data will be drawn as displayed in print method (not transposed automatically).
211+
212+
Also, helper function ``pandas.tools.plotting.table`` is added to create a table from ``DataFrame`` and ``Series``, and add it to an ``matplotlib.Axes``.
213+
214+
204215
MultiIndexing Using Slicers
205216
~~~~~~~~~~~~~~~~~~~~~~~~~~~
206217

doc/source/visualization.rst

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,48 @@ Here is an example of one way to easily plot group means with standard deviation
415415
@savefig errorbar_example.png
416416
means.plot(yerr=errors, ax=ax, kind='bar')
417417
418+
Plotting With Table
419+
~~~~~~~~~~~~~~~~~~~~~~~~
420+
421+
.. versionadded:: 0.14
422+
423+
Plotting with matplotlib table is now supported in the ``DataFrame.plot`` and ``Series.plot`` by a ``table`` keyword. The ``table`` keyword can accept ``bool``, ``DataFrame`` or ``Series``. The simple way to draw a table is to specify ``table=True``. Data will be transposed to meet matplotlib's default layout.
424+
425+
.. ipython:: python
426+
427+
fig, ax = plt.subplots(1, 1)
428+
df = DataFrame(rand(5, 3), columns=['a', 'b', 'c'])
429+
ax.get_xaxis().set_visible(False) # Hide Ticks
430+
431+
@savefig line_plot_table_true.png
432+
df.plot(table=True, ax=ax)
433+
434+
Also, you can pass different ``DataFrame`` or ``Series`` for ``table`` keyword. The data will be drawn as displayed in print method (not transposed automatically). If required, it should be transposed manually as below example.
435+
436+
.. ipython:: python
437+
438+
fig, ax = plt.subplots(1, 1)
439+
ax.get_xaxis().set_visible(False) # Hide Ticks
440+
@savefig line_plot_table_data.png
441+
df.plot(table=np.round(df.T, 2), ax=ax)
442+
443+
444+
Finally, there is a helper function ``pandas.tools.plotting.table`` to create a table from ``DataFrame`` and ``Series``, and add it to an ``matplotlib.Axes``. This function can accept keywords which matplotlib table has.
445+
446+
.. ipython:: python
447+
448+
from pandas.tools.plotting import table
449+
fig, ax = plt.subplots(1, 1)
450+
451+
table(ax, np.round(df.describe(), 2),
452+
loc='upper right', colWidths=[0.2, 0.2, 0.2])
453+
454+
@savefig line_plot_table_describe.png
455+
df.plot(ax=ax, ylim=(0, 2), legend=None)
456+
457+
**Note**: You can get table instances on the axes using ``axes.tables`` property for further decorations. See the `matplotlib table documenation <http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes.table>`__ for more.
458+
459+
418460
.. _visualization.scatter_matrix:
419461

420462
Scatter plot matrix

pandas/tests/test_graphics.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,11 @@ def test_errorbar_plot(self):
309309
with tm.assertRaises(TypeError):
310310
s.plot(yerr=s_err)
311311

312+
def test_table(self):
313+
_check_plot_works(self.series.plot, table=True)
314+
_check_plot_works(self.series.plot, table=self.series)
315+
316+
312317
@tm.mplskip
313318
class TestDataFramePlots(tm.TestCase):
314319
def setUp(self):
@@ -1335,6 +1340,18 @@ def test_errorbar_asymmetrical(self):
13351340

13361341
tm.close()
13371342

1343+
def test_table(self):
1344+
df = DataFrame(np.random.rand(10, 3),
1345+
index=list(string.ascii_letters[:10]))
1346+
_check_plot_works(df.plot, table=True)
1347+
_check_plot_works(df.plot, table=df)
1348+
1349+
ax = df.plot()
1350+
self.assert_(len(ax.tables) == 0)
1351+
plotting.table(ax, df.T)
1352+
self.assert_(len(ax.tables) == 1)
1353+
1354+
13381355
@tm.mplskip
13391356
class TestDataFrameGroupByPlots(tm.TestCase):
13401357
def tearDown(self):

pandas/tools/plotting.py

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,8 @@ def __init__(self, data, kind=None, by=None, subplots=False, sharex=True,
793793
ax=None, fig=None, title=None, xlim=None, ylim=None,
794794
xticks=None, yticks=None,
795795
sort_columns=False, fontsize=None,
796-
secondary_y=False, colormap=None, **kwds):
796+
secondary_y=False, colormap=None,
797+
table=False, **kwds):
797798

798799
self.data = data
799800
self.by = by
@@ -849,6 +850,8 @@ def __init__(self, data, kind=None, by=None, subplots=False, sharex=True,
849850
else:
850851
self.colormap = colormap
851852

853+
self.table = table
854+
852855
self.kwds = kwds
853856

854857
self._validate_color_args()
@@ -915,6 +918,7 @@ def generate(self):
915918
self._compute_plot_data()
916919
self._setup_subplots()
917920
self._make_plot()
921+
self._add_table()
918922
self._post_plot_logic()
919923
self._adorn_subplots()
920924

@@ -1005,6 +1009,21 @@ def _compute_plot_data(self):
10051009
def _make_plot(self):
10061010
raise NotImplementedError
10071011

1012+
def _add_table(self):
1013+
if self.table is False:
1014+
return
1015+
elif self.table is True:
1016+
from pandas.core.frame import DataFrame
1017+
if isinstance(self.data, Series):
1018+
data = DataFrame(self.data, columns=[self.data.name])
1019+
elif isinstance(self.data, DataFrame):
1020+
data = self.data
1021+
data = data.transpose()
1022+
else:
1023+
data = self.table
1024+
ax = self._get_ax(0)
1025+
table(ax, data)
1026+
10081027
def _post_plot_logic(self):
10091028
pass
10101029

@@ -1664,7 +1683,6 @@ def _post_plot_logic(self):
16641683
for ax in self.axes:
16651684
ax.legend(loc='best')
16661685

1667-
16681686
class BarPlot(MPLPlot):
16691687

16701688
_default_rot = {'bar': 90, 'barh': 0}
@@ -2594,6 +2612,47 @@ def _grouped_plot_by_column(plotf, data, columns=None, by=None,
25942612
return fig, axes
25952613

25962614

2615+
def table(ax, data, rowLabels=None, colLabels=None,
2616+
**kwargs):
2617+
2618+
"""
2619+
Helper function to convert DataFrame and Series to matplotlib.table
2620+
2621+
Parameters
2622+
----------
2623+
`ax`: Matplotlib axes object
2624+
`data`: DataFrame or Series
2625+
data for table contents
2626+
`kwargs`: keywords, optional
2627+
keyword arguments which passed to matplotlib.table.table.
2628+
If `rowLabels` or `colLabels` is not specified, data index or column name will be used.
2629+
2630+
Returns
2631+
-------
2632+
matplotlib table object
2633+
"""
2634+
from pandas import DataFrame
2635+
if isinstance(data, Series):
2636+
data = DataFrame(data, columns=[data.name])
2637+
elif isinstance(data, DataFrame):
2638+
pass
2639+
else:
2640+
raise ValueError('Input data must be dataframe or series')
2641+
2642+
if rowLabels is None:
2643+
rowLabels = data.index
2644+
2645+
if colLabels is None:
2646+
colLabels = data.columns
2647+
2648+
cellText = data.values
2649+
2650+
import matplotlib.table
2651+
table = matplotlib.table.table(ax, cellText=cellText,
2652+
rowLabels=rowLabels, colLabels=colLabels, **kwargs)
2653+
return table
2654+
2655+
25972656
def _get_layout(nplots):
25982657
if nplots == 1:
25992658
return (1, 1)

0 commit comments

Comments
 (0)