Skip to content

API: Remove integer position args from xy for plotting #20371

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

Closed
wants to merge 2 commits into from
Closed
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
23 changes: 11 additions & 12 deletions pandas/plotting/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1728,6 +1728,11 @@ def _plot(data, x=None, y=None, subplots=False,
klass = _plot_klass[kind]
else:
raise ValueError("%r is not a valid plot kind" % kind)
xy_ints = is_integer(x) or is_integer(y)
if xy_ints and not data.columns.holds_integer():
raise ValueError(
"x and y must be labels that match column names in data"
)

if kind in _dataframe_kinds:
if isinstance(data, ABCDataFrame):
Expand All @@ -1743,26 +1748,20 @@ def _plot(data, x=None, y=None, subplots=False,
msg = "{0} requires either y column or 'subplots=True'"
raise ValueError(msg.format(kind))
elif y is not None:
if is_integer(y) and not data.columns.holds_integer():
y = data.columns[y]
# converted to series actually. copy to not modify
data = data[y].copy()
data.index.name = y
plot_obj = klass(data, subplots=subplots, ax=ax, kind=kind, **kwds)
else:
if isinstance(data, ABCDataFrame):
if x is not None:
if is_integer(x) and not data.columns.holds_integer():
x = data.columns[x]
elif not isinstance(data[x], ABCSeries):
raise ValueError("x must be a label or position")
if not isinstance(data[x], ABCSeries):
raise ValueError("x must be a label")
data = data.set_index(x)

if y is not None:
if is_integer(y) and not data.columns.holds_integer():
y = data.columns[y]
elif not isinstance(data[y], ABCSeries):
raise ValueError("y must be a label or position")
if not isinstance(data[y], ABCSeries):
raise ValueError("y must be a label")
label = kwds['label'] if 'label' in kwds else y
series = data[y].copy() # Don't modify
series.name = label
Expand All @@ -1787,8 +1786,8 @@ def _plot(data, x=None, y=None, subplots=False,
- 'hexbin' : hexbin plot"""
series_kind = ""

df_coord = """x : label or position, default None
y : label or position, default None
df_coord = """x : label, default None
y : label, default None
Allows plotting of one column versus another"""
series_coord = ""

Expand Down
42 changes: 23 additions & 19 deletions pandas/tests/plotting/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,6 @@ def test_donot_overwrite_index_name(self):
def test_plot_xy(self):
# columns.inferred_type == 'string'
df = self.tdf
self._check_data(df.plot(x=0, y=1), df.set_index('A')['B'].plot())
self._check_data(df.plot(x=0), df.set_index('A').plot())
self._check_data(df.plot(y=0), df.B.plot())
self._check_data(df.plot(x='A', y='B'), df.set_index('A').B.plot())
self._check_data(df.plot(x='A'), df.set_index('A').plot())
self._check_data(df.plot(y='B'), df.B.plot())
Expand Down Expand Up @@ -1019,7 +1016,6 @@ def test_plot_scatter(self):
columns=['x', 'y', 'z', 'four'])

_check_plot_works(df.plot.scatter, x='x', y='y')
_check_plot_works(df.plot.scatter, x=1, y=2)

with pytest.raises(TypeError):
df.plot.scatter(x='x')
Expand Down Expand Up @@ -1054,17 +1050,15 @@ def test_plot_scatter_with_c(self):
index=list(string.ascii_letters[:6]),
columns=['x', 'y', 'z', 'four'])

axes = [df.plot.scatter(x='x', y='y', c='z'),
df.plot.scatter(x=0, y=1, c=2)]
for ax in axes:
# default to Greys
assert ax.collections[0].cmap.name == 'Greys'
axes = df.plot.scatter(x='x', y='y', c='z')

if self.mpl_ge_1_3_1:
# default to Greys
assert axes.collections[0].cmap.name == 'Greys'

# n.b. there appears to be no public method to get the colorbar
# label
assert ax.collections[0].colorbar._label == 'z'
if self.mpl_ge_1_3_1:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TomAugspurger we should be able to blow this code away as we > 1.4.3, yes (separate PR)

# n.b. there appears to be no public method to get the colorbar
# label
assert axes.collections[0].colorbar._label == 'z'

cm = 'cubehelix'
ax = df.plot.scatter(x='x', y='y', c='z', colormap=cm)
Expand All @@ -1075,7 +1069,7 @@ def test_plot_scatter_with_c(self):
assert ax.collections[0].colorbar is None

# verify that we can still plot a solid color
ax = df.plot.scatter(x=0, y=1, c='red')
ax = df.plot.scatter(x='x', y='y', c='red')
assert ax.collections[0].colorbar is None
self._check_colors(ax.collections, facecolors=['r'])

Expand Down Expand Up @@ -2172,14 +2166,27 @@ def test_invalid_kind(self):

@pytest.mark.parametrize("x,y", [
(['B', 'C'], 'A'),
('A', ['B', 'C'])
('A', ['B', 'C']),
(0, 'A'),
('A', 0),
(0, 1)
])
def test_invalid_xy_args(self, x, y):
# GH 18671
# GH 18671 and # GH 20056
df = DataFrame({"A": [1, 2], 'B': [3, 4], 'C': [5, 6]})
with pytest.raises(ValueError):
df.plot(x=x, y=y)

@pytest.mark.parametrize("x,y,colnames", [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a test that checks the raise when passing ints and a non-int index

(0, 1, [0, 1]),
(1, 'A', ['A', 1])
])
def test_xy_args_ints(self, x, y, colnames):
# GH 20056
df = DataFrame({"A": [1, 2], 'B': [3, 4]})
df.columns = colnames
_check_plot_works(df.plot, x=x, y=y)

@pytest.mark.parametrize("x,y", [
('A', 'B'),
('B', 'A')
Expand Down Expand Up @@ -2255,9 +2262,6 @@ def test_pie_df(self):
ax = _check_plot_works(df.plot.pie, y='Y')
self._check_text_labels(ax.texts, df.index)

ax = _check_plot_works(df.plot.pie, y=2)
self._check_text_labels(ax.texts, df.index)

# _check_plot_works adds an ax so catch warning. see GH #13188
with tm.assert_produces_warning(UserWarning):
axes = _check_plot_works(df.plot.pie,
Expand Down