Skip to content

Commit 2f4cd4b

Browse files
committed
ENH: plot only numeric data
does not raise anymore if there exists some valid data forgot a test
1 parent 44ab793 commit 2f4cd4b

File tree

5 files changed

+82
-14
lines changed

5 files changed

+82
-14
lines changed

RELEASE.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ pandas 0.11.1
6767
to specify custom column names of the returned DataFrame (GH3649_),
6868
thanks @hoechenberger
6969
- ``read_html`` no longer performs hard date conversion
70+
- Plotting functions now raise a ``TypeError`` before trying to plot anything
71+
if the associated objects have have a dtype of ``object`` (GH1818_). This
72+
happens before any drawing takes place which elimnates any spurious plots
73+
from showing up.
7074

7175
**API Changes**
7276

@@ -227,6 +231,7 @@ pandas 0.11.1
227231
.. _GH3659: https://github.com/pydata/pandas/issues/3659
228232
.. _GH3649: https://github.com/pydata/pandas/issues/3649
229233
.. _Gh3616: https://github.com/pydata/pandas/issues/3616
234+
.. _GH1818: https://github.com/pydata/pandas/issues/1818
230235

231236
pandas 0.11.0
232237
=============

doc/source/v0.11.1.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ API changes
6262
``df.iloc[mask]`` will raise a ``ValueError``
6363

6464

65+
6566
Enhancements
6667
~~~~~~~~~~~~
6768

@@ -158,6 +159,11 @@ Enhancements
158159
- ``pd.melt()`` now accepts the optional parameters ``var_name`` and ``value_name``
159160
to specify custom column names of the returned DataFrame.
160161

162+
- Plotting functions now raise a ``TypeError`` before trying to plot anything
163+
if the associated objects have have a ``dtype`` of ``object`` (GH1818_).
164+
This happens before any drawing takes place which elimnates any spurious
165+
plots from showing up.
166+
161167
Bug Fixes
162168
~~~~~~~~~
163169

@@ -227,3 +233,4 @@ on GitHub for a complete list.
227233
.. _GH3605: https://github.com/pydata/pandas/issues/3605
228234
.. _GH3606: https://github.com/pydata/pandas/issues/3606
229235
.. _GH3656: https://github.com/pydata/pandas/issues/3656
236+
.. _GH1818: https://github.com/pydata/pandas/issues/1818

pandas/tests/test_graphics.py

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,27 @@ def test_bootstrap_plot(self):
187187
from pandas.tools.plotting import bootstrap_plot
188188
_check_plot_works(bootstrap_plot, self.ts, size=10)
189189

190+
@slow
191+
def test_all_invalid_plot_data(self):
192+
s = Series(list('abcd'))
193+
kinds = 'line', 'bar', 'barh', 'kde', 'density'
194+
195+
for kind in kinds:
196+
self.assertRaises(TypeError, s.plot, kind=kind)
197+
198+
@slow
199+
def test_partially_invalid_plot_data(self):
200+
s = Series(['a', 'b', 1.0, 2])
201+
kinds = 'line', 'bar', 'barh', 'kde', 'density'
202+
203+
for kind in kinds:
204+
self.assertRaises(TypeError, s.plot, kind=kind)
205+
206+
@slow
207+
def test_invalid_kind(self):
208+
s = Series([1, 2])
209+
self.assertRaises(ValueError, s.plot, kind='aasdf')
210+
190211

191212
class TestDataFramePlots(unittest.TestCase):
192213

@@ -249,11 +270,9 @@ def test_nonnumeric_exclude(self):
249270
plt.close('all')
250271

251272
df = DataFrame({'A': ["x", "y", "z"], 'B': [1,2,3]})
252-
ax = df.plot(raise_on_error=False) # it works
273+
ax = df.plot()
253274
self.assert_(len(ax.get_lines()) == 1) #B was plotted
254275

255-
self.assertRaises(Exception, df.plot)
256-
257276
@slow
258277
def test_label(self):
259278
import matplotlib.pyplot as plt
@@ -688,6 +707,26 @@ def test_unordered_ts(self):
688707
ydata = ax.lines[0].get_ydata()
689708
self.assert_(np.all(ydata == np.array([1.0, 2.0, 3.0])))
690709

710+
@slow
711+
def test_all_invalid_plot_data(self):
712+
kinds = 'line', 'bar', 'barh', 'kde', 'density'
713+
df = DataFrame(list('abcd'))
714+
for kind in kinds:
715+
self.assertRaises(TypeError, df.plot, kind=kind)
716+
717+
@slow
718+
def test_partially_invalid_plot_data(self):
719+
kinds = 'line', 'bar', 'barh', 'kde', 'density'
720+
df = DataFrame(np.random.randn(10, 2), dtype=object)
721+
df[np.random.rand(df.shape[0]) > 0.5] = 'a'
722+
for kind in kinds:
723+
self.assertRaises(TypeError, df.plot, kind=kind)
724+
725+
@slow
726+
def test_invalid_kind(self):
727+
df = DataFrame(np.random.randn(10, 2))
728+
self.assertRaises(ValueError, df.plot, kind='aasdf')
729+
691730
class TestDataFrameGroupByPlots(unittest.TestCase):
692731

693732
@classmethod

pandas/tools/plotting.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# being a bit too dynamic
22
# pylint: disable=E1101
3-
from itertools import izip
43
import datetime
54
import warnings
65
import re
@@ -875,7 +874,27 @@ def _get_layout(self):
875874
return (len(self.data.columns), 1)
876875

877876
def _compute_plot_data(self):
878-
pass
877+
try:
878+
# might be a frame
879+
numeric_data = self.data._get_numeric_data()
880+
except AttributeError:
881+
# a series, but no object dtypes allowed!
882+
if self.data.dtype == np.object_:
883+
raise TypeError('invalid dtype for plotting, please cast to a '
884+
'numeric dtype explicitly if you want to plot')
885+
886+
numeric_data = self.data
887+
888+
try:
889+
is_empty = numeric_data.empty
890+
except AttributeError:
891+
is_empty = not len(numeric_data)
892+
893+
# no empty frames or series allowed
894+
if is_empty:
895+
raise TypeError('No numeric data to plot')
896+
897+
self.data = numeric_data
879898

880899
def _make_plot(self):
881900
raise NotImplementedError
@@ -1204,7 +1223,7 @@ def _make_plot(self):
12041223
else:
12051224
msg = msg + ('\nConsider setting raise_on_error=False'
12061225
'to suppress')
1207-
raise Exception(msg)
1226+
raise TypeError(msg)
12081227

12091228
self._make_legend(lines, labels)
12101229

@@ -1238,7 +1257,7 @@ def _plot(data, col_num, ax, label, style, **kwds):
12381257
else:
12391258
msg = msg + ('\nConsider setting raise_on_error=False'
12401259
'to suppress')
1241-
raise Exception(msg)
1260+
raise TypeError(msg)
12421261

12431262
if isinstance(data, Series):
12441263
ax = self._get_ax(0) # self.axes[0]
@@ -1610,8 +1629,8 @@ def plot_series(series, label=None, kind='line', use_index=True, rot=None,
16101629
If not passed, uses gca()
16111630
style : string, default matplotlib default
16121631
matplotlib line style to use
1613-
grid : matplot grid
1614-
legend: matplot legende
1632+
grid : matplotlib grid
1633+
legend: matplotlib legend
16151634
logx : boolean, default False
16161635
For line plots, use log scaling on x axis
16171636
logy : boolean, default False
@@ -1633,6 +1652,8 @@ def plot_series(series, label=None, kind='line', use_index=True, rot=None,
16331652
klass = BarPlot
16341653
elif kind == 'kde':
16351654
klass = KdePlot
1655+
else:
1656+
raise ValueError('Invalid chart type given %s' % kind)
16361657

16371658
"""
16381659
If no axis is specified, we check whether there are existing figures.

pandas/tseries/tests/test_plotting.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,18 +87,14 @@ def test_nonnumeric_exclude(self):
8787

8888
idx = date_range('1/1/1987', freq='A', periods=3)
8989
df = DataFrame({'A': ["x", "y", "z"], 'B': [1,2,3]}, idx)
90-
self.assertRaises(Exception, df.plot)
9190

9291
plt.close('all')
9392
ax = df.plot(raise_on_error=False) # it works
9493
self.assert_(len(ax.get_lines()) == 1) #B was plotted
9594

9695
plt.close('all')
97-
self.assertRaises(Exception, df.A.plot)
9896

99-
plt.close('all')
100-
ax = df['A'].plot(raise_on_error=False) # it works
101-
self.assert_(len(ax.get_lines()) == 0)
97+
self.assertRaises(TypeError, df['A'].plot)
10298

10399
@slow
104100
def test_tsplot(self):

0 commit comments

Comments
 (0)