Skip to content

Commit e35866c

Browse files
simonjayhawkinsnofarmish
authored andcommitted
Revert "Inconsistent indexes for tick label plotting (pandas-dev#28733)" (pandas-dev#39235)
1 parent 0acc13a commit e35866c

File tree

4 files changed

+8
-96
lines changed

4 files changed

+8
-96
lines changed

doc/source/whatsnew/v1.2.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ Plotting
751751

752752
- Bug in :meth:`DataFrame.plot` was rotating xticklabels when ``subplots=True``, even if the x-axis wasn't an irregular time series (:issue:`29460`)
753753
- Bug in :meth:`DataFrame.plot` where a marker letter in the ``style`` keyword sometimes caused a ``ValueError`` (:issue:`21003`)
754-
- Bug in :meth:`DataFrame.plot.bar` and :meth:`Series.plot.bar` where ticks positions were assigned by value order instead of using the actual value for numeric or a smart ordering for string (:issue:`26186`, :issue:`11465`)
754+
- Bug in :meth:`DataFrame.plot.bar` and :meth:`Series.plot.bar` where ticks positions were assigned by value order instead of using the actual value for numeric or a smart ordering for string (:issue:`26186`, :issue:`11465`). This fix has been reverted in pandas 1.2.1, see :doc:`v1.2.1`
755755
- Twinned axes were losing their tick labels which should only happen to all but the last row or column of 'externally' shared axes (:issue:`33819`)
756756
- Bug in :meth:`Series.plot` and :meth:`DataFrame.plot` was throwing a :exc:`ValueError` when the Series or DataFrame was
757757
indexed by a :class:`.TimedeltaIndex` with a fixed frequency and the x-axis lower limit was greater than the upper limit (:issue:`37454`)

doc/source/whatsnew/v1.2.1.rst

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ Fixed regressions
3434
- Fixed regression that raised ``AttributeError`` with PyArrow versions [0.16.0, 1.0.0) (:issue:`38801`)
3535
- Fixed regression in :func:`pandas.testing.assert_frame_equal` raising ``TypeError`` with ``check_like=True`` when :class:`Index` or columns have mixed dtype (:issue:`39168`)
3636

37+
We have reverted a commit that resulted in several plotting related regressions in pandas 1.2.0 (:issue:`38969`, :issue:`38736`, :issue:`38865`, :issue:`38947` and :issue:`39126`).
38+
As a result, bugs reported as fixed in pandas 1.2.0 related to inconsistent tick labeling in bar plots are again present (:issue:`26186` and :issue:`11465`)
39+
3740
.. ---------------------------------------------------------------------------
3841
3942
.. _whatsnew_121.bug_fixes:

pandas/plotting/_matplotlib/core.py

+4-21
Original file line numberDiff line numberDiff line change
@@ -1369,6 +1369,7 @@ def __init__(self, data, **kwargs):
13691369
self.bar_width = kwargs.pop("width", 0.5)
13701370
pos = kwargs.pop("position", 0.5)
13711371
kwargs.setdefault("align", "center")
1372+
self.tick_pos = np.arange(len(data))
13721373

13731374
self.bottom = kwargs.pop("bottom", 0)
13741375
self.left = kwargs.pop("left", 0)
@@ -1391,16 +1392,7 @@ def __init__(self, data, **kwargs):
13911392
self.tickoffset = self.bar_width * pos
13921393
self.lim_offset = 0
13931394

1394-
if isinstance(self.data.index, ABCMultiIndex):
1395-
if kwargs["ax"] is not None and kwargs["ax"].has_data():
1396-
warnings.warn(
1397-
"Redrawing a bar plot with a MultiIndex is not supported "
1398-
+ "and may lead to inconsistent label positions.",
1399-
UserWarning,
1400-
)
1401-
self.ax_index = np.arange(len(data))
1402-
else:
1403-
self.ax_index = self.data.index
1395+
self.ax_pos = self.tick_pos - self.tickoffset
14041396

14051397
def _args_adjust(self):
14061398
if is_list_like(self.bottom):
@@ -1427,15 +1419,6 @@ def _make_plot(self):
14271419

14281420
for i, (label, y) in enumerate(self._iter_data(fillna=0)):
14291421
ax = self._get_ax(i)
1430-
1431-
if self.orientation == "vertical":
1432-
ax.xaxis.update_units(self.ax_index)
1433-
self.tick_pos = ax.convert_xunits(self.ax_index).astype(np.int)
1434-
elif self.orientation == "horizontal":
1435-
ax.yaxis.update_units(self.ax_index)
1436-
self.tick_pos = ax.convert_yunits(self.ax_index).astype(np.int)
1437-
self.ax_pos = self.tick_pos - self.tickoffset
1438-
14391422
kwds = self.kwds.copy()
14401423
if self._is_series:
14411424
kwds["color"] = colors
@@ -1507,8 +1490,8 @@ def _post_plot_logic(self, ax: "Axes", data):
15071490
str_index = [pprint_thing(key) for key in range(data.shape[0])]
15081491
name = self._get_index_name()
15091492

1510-
s_edge = self.ax_pos.min() - 0.25 + self.lim_offset
1511-
e_edge = self.ax_pos.max() + 0.25 + self.bar_width + self.lim_offset
1493+
s_edge = self.ax_pos[0] - 0.25 + self.lim_offset
1494+
e_edge = self.ax_pos[-1] + 0.25 + self.bar_width + self.lim_offset
15121495

15131496
self._decorate_ticks(ax, name, str_index, s_edge, e_edge)
15141497

pandas/tests/plotting/frame/test_frame.py

-74
Original file line numberDiff line numberDiff line change
@@ -2191,80 +2191,6 @@ def test_xlabel_ylabel_dataframe_plane_plot(self, kind, xlabel, ylabel):
21912191
assert ax.get_xlabel() == (xcol if xlabel is None else xlabel)
21922192
assert ax.get_ylabel() == (ycol if ylabel is None else ylabel)
21932193

2194-
@pytest.mark.parametrize("method", ["bar", "barh"])
2195-
def test_bar_ticklabel_consistence(self, method):
2196-
# Draw two consecutiv bar plot with consistent ticklabels
2197-
# The labels positions should not move between two drawing on the same axis
2198-
# GH: 26186
2199-
def get_main_axis(ax):
2200-
if method == "barh":
2201-
return ax.yaxis
2202-
elif method == "bar":
2203-
return ax.xaxis
2204-
2205-
# Plot the first bar plot
2206-
data = {"A": 0, "B": 3, "C": -4}
2207-
df = DataFrame.from_dict(data, orient="index", columns=["Value"])
2208-
ax = getattr(df.plot, method)()
2209-
ax.get_figure().canvas.draw()
2210-
2211-
# Retrieve the label positions for the first drawing
2212-
xticklabels = [t.get_text() for t in get_main_axis(ax).get_ticklabels()]
2213-
label_positions_1 = dict(zip(xticklabels, get_main_axis(ax).get_ticklocs()))
2214-
2215-
# Modify the dataframe order and values and plot on same axis
2216-
df = df.sort_values("Value") * -2
2217-
ax = getattr(df.plot, method)(ax=ax, color="red")
2218-
ax.get_figure().canvas.draw()
2219-
2220-
# Retrieve the label positions for the second drawing
2221-
xticklabels = [t.get_text() for t in get_main_axis(ax).get_ticklabels()]
2222-
label_positions_2 = dict(zip(xticklabels, get_main_axis(ax).get_ticklocs()))
2223-
2224-
# Assert that the label positions did not change between the plotting
2225-
assert label_positions_1 == label_positions_2
2226-
2227-
def test_bar_numeric(self):
2228-
# Bar plot with numeric index have tick location values equal to index
2229-
# values
2230-
# GH: 11465
2231-
df = DataFrame(np.random.rand(10), index=np.arange(10, 20))
2232-
ax = df.plot.bar()
2233-
ticklocs = ax.xaxis.get_ticklocs()
2234-
expected = np.arange(10, 20, dtype=np.int64)
2235-
tm.assert_numpy_array_equal(ticklocs, expected)
2236-
2237-
def test_bar_multiindex(self):
2238-
# Test from pandas/doc/source/user_guide/visualization.rst
2239-
# at section Plotting With Error Bars
2240-
# Related to issue GH: 26186
2241-
2242-
ix3 = pd.MultiIndex.from_arrays(
2243-
[
2244-
["a", "a", "a", "a", "b", "b", "b", "b"],
2245-
["foo", "foo", "bar", "bar", "foo", "foo", "bar", "bar"],
2246-
],
2247-
names=["letter", "word"],
2248-
)
2249-
2250-
df3 = DataFrame(
2251-
{"data1": [3, 2, 4, 3, 2, 4, 3, 2], "data2": [6, 5, 7, 5, 4, 5, 6, 5]},
2252-
index=ix3,
2253-
)
2254-
2255-
# Group by index labels and take the means and standard deviations
2256-
# for each group
2257-
gp3 = df3.groupby(level=("letter", "word"))
2258-
means = gp3.mean()
2259-
errors = gp3.std()
2260-
2261-
# No assertion we just ensure that we can plot a MultiIndex bar plot
2262-
# and are getting a UserWarning if redrawing
2263-
with tm.assert_produces_warning(None):
2264-
ax = means.plot.bar(yerr=errors, capsize=4)
2265-
with tm.assert_produces_warning(UserWarning):
2266-
means.plot.bar(yerr=errors, capsize=4, ax=ax)
2267-
22682194

22692195
def _generate_4_axes_via_gridspec():
22702196
import matplotlib as mpl

0 commit comments

Comments
 (0)