Skip to content

Add layout keyword to dataframe.hist() #4031

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 29, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/source/release.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ pandas 0.12
(:issue:`3910`, :issue:`3914`)
- ``read_csv`` will now throw a more informative error message when a file
contains no columns, e.g., all newline characters
- Added ``layout`` keyword to DataFrame.hist() for more customizable layout (:issue:`4050`)

**API Changes**

Expand Down
25 changes: 25 additions & 0 deletions pandas/tests/test_graphics.py
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,31 @@ def test_hist(self):
# propagate attr exception from matplotlib.Axes.hist
self.assertRaises(AttributeError, ser.hist, foo='bar')

@slow
def test_hist_layout(self):
import matplotlib.pyplot as plt
plt.close('all')
df = DataFrame(np.random.randn(100, 4))

layout_to_expected_size = (
{'layout': None, 'expected_size': (2, 2)}, # default is 2x2
{'layout': (2, 2), 'expected_size': (2, 2)},
{'layout': (4, 1), 'expected_size': (4, 1)},
{'layout': (1, 4), 'expected_size': (1, 4)},
{'layout': (3, 3), 'expected_size': (3, 3)},
)

for layout_test in layout_to_expected_size:
ax = df.hist(layout=layout_test['layout'])
self.assert_(len(ax) == layout_test['expected_size'][0])
self.assert_(len(ax[0]) == layout_test['expected_size'][1])

# layout too small for all 4 plots
self.assertRaises(ValueError, df.hist, layout=(1, 1))

# invalid format for layout
self.assertRaises(ValueError, df.hist, layout=(1,))

@slow
def test_scatter(self):
_skip_if_no_scipy()
Expand Down
24 changes: 17 additions & 7 deletions pandas/tools/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -1890,7 +1890,7 @@ def plot_group(group, ax):

def hist_frame(data, column=None, by=None, grid=True, xlabelsize=None,
xrot=None, ylabelsize=None, yrot=None, ax=None, sharex=False,
sharey=False, figsize=None, **kwds):
sharey=False, figsize=None, layout=None, **kwds):
"""
Draw Histogram the DataFrame's series using matplotlib / pylab.

Expand All @@ -1916,6 +1916,7 @@ def hist_frame(data, column=None, by=None, grid=True, xlabelsize=None,
sharey : bool, if True, the Y axis will be shared amongst all subplots.
figsize : tuple
The size of the figure to create in inches by default
layout: (optional) a tuple (rows, columns) for the layout of the histograms
kwds : other plotting keyword arguments
To be passed to hist function
"""
Expand Down Expand Up @@ -1943,12 +1944,21 @@ def hist_frame(data, column=None, by=None, grid=True, xlabelsize=None,

import matplotlib.pyplot as plt
n = len(data.columns)
rows, cols = 1, 1
while rows * cols < n:
if cols > rows:
rows += 1
else:
cols += 1

if layout is not None:
if not isinstance(layout, (tuple, list)) or len(layout) != 2:
raise ValueError('Layout must be a tuple of (rows, columns)')

rows, cols = layout
if rows * cols < n:
raise ValueError('Layout of %sx%s is incompatible with %s columns' % (rows, cols, n))
else:
rows, cols = 1, 1
while rows * cols < n:
if cols > rows:
rows += 1
else:
cols += 1
fig, axes = _subplots(nrows=rows, ncols=cols, ax=ax, squeeze=False,
sharex=sharex, sharey=sharey, figsize=figsize)

Expand Down