Skip to content

Commit d7d8f2d

Browse files
masongallojreback
authored andcommitted
API: Improper x/y arg given to df.plot (#18695)
1 parent 2efd67f commit d7d8f2d

File tree

3 files changed

+29
-6
lines changed

3 files changed

+29
-6
lines changed

doc/source/whatsnew/v0.22.0.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ I/O
284284
Plotting
285285
^^^^^^^^
286286

287-
-
287+
- :func: `DataFrame.plot` now raises a ``ValueError`` when the ``x`` or ``y`` argument is improperly formed (:issue:`18671`)
288288
-
289289
-
290290

pandas/plotting/_core.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
is_number,
2020
is_hashable,
2121
is_iterator)
22-
from pandas.core.dtypes.generic import ABCSeries
22+
from pandas.core.dtypes.generic import ABCSeries, ABCDataFrame
2323

2424
from pandas.core.common import AbstractMethodError, _try_sort, _any_not_none
2525
from pandas.core.generic import _shared_docs, _shared_doc_kwargs
@@ -1680,17 +1680,16 @@ def _plot(data, x=None, y=None, subplots=False,
16801680
else:
16811681
raise ValueError("%r is not a valid plot kind" % kind)
16821682

1683-
from pandas import DataFrame
16841683
if kind in _dataframe_kinds:
1685-
if isinstance(data, DataFrame):
1684+
if isinstance(data, ABCDataFrame):
16861685
plot_obj = klass(data, x=x, y=y, subplots=subplots, ax=ax,
16871686
kind=kind, **kwds)
16881687
else:
16891688
raise ValueError("plot kind %r can only be used for data frames"
16901689
% kind)
16911690

16921691
elif kind in _series_kinds:
1693-
if isinstance(data, DataFrame):
1692+
if isinstance(data, ABCDataFrame):
16941693
if y is None and subplots is False:
16951694
msg = "{0} requires either y column or 'subplots=True'"
16961695
raise ValueError(msg.format(kind))
@@ -1702,15 +1701,19 @@ def _plot(data, x=None, y=None, subplots=False,
17021701
data.index.name = y
17031702
plot_obj = klass(data, subplots=subplots, ax=ax, kind=kind, **kwds)
17041703
else:
1705-
if isinstance(data, DataFrame):
1704+
if isinstance(data, ABCDataFrame):
17061705
if x is not None:
17071706
if is_integer(x) and not data.columns.holds_integer():
17081707
x = data.columns[x]
1708+
elif not isinstance(data[x], ABCSeries):
1709+
raise ValueError("x must be a label or position")
17091710
data = data.set_index(x)
17101711

17111712
if y is not None:
17121713
if is_integer(y) and not data.columns.holds_integer():
17131714
y = data.columns[y]
1715+
elif not isinstance(data[y], ABCSeries):
1716+
raise ValueError("y must be a label or position")
17141717
label = kwds['label'] if 'label' in kwds else y
17151718
series = data[y].copy() # Don't modify
17161719
series.name = label

pandas/tests/plotting/test_frame.py

+20
Original file line numberDiff line numberDiff line change
@@ -2170,6 +2170,26 @@ def test_invalid_kind(self):
21702170
with pytest.raises(ValueError):
21712171
df.plot(kind='aasdf')
21722172

2173+
@pytest.mark.parametrize("x,y", [
2174+
(['B', 'C'], 'A'),
2175+
('A', ['B', 'C'])
2176+
])
2177+
def test_invalid_xy_args(self, x, y):
2178+
# GH 18671
2179+
df = DataFrame({"A": [1, 2], 'B': [3, 4], 'C': [5, 6]})
2180+
with pytest.raises(ValueError):
2181+
df.plot(x=x, y=y)
2182+
2183+
@pytest.mark.parametrize("x,y", [
2184+
('A', 'B'),
2185+
('B', 'A')
2186+
])
2187+
def test_invalid_xy_args_dup_cols(self, x, y):
2188+
# GH 18671
2189+
df = DataFrame([[1, 3, 5], [2, 4, 6]], columns=list('AAB'))
2190+
with pytest.raises(ValueError):
2191+
df.plot(x=x, y=y)
2192+
21732193
@pytest.mark.slow
21742194
def test_hexbin_basic(self):
21752195
df = self.hexbin_df

0 commit comments

Comments
 (0)