Skip to content

Commit 3f02e63

Browse files
nrebenajreback
authored andcommitted
BUG: Plotting use FixedLocator (#26185)
closes #7612 closes #15912 closes #22334
1 parent 2266911 commit 3f02e63

File tree

3 files changed

+45
-3
lines changed

3 files changed

+45
-3
lines changed

doc/source/whatsnew/v0.25.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ Plotting
374374

375375
- Fixed bug where :class:`api.extensions.ExtensionArray` could not be used in matplotlib plotting (:issue:`25587`)
376376
- Bug in an error message in :meth:`DataFrame.plot`. Improved the error message if non-numerics are passed to :meth:`DataFrame.plot` (:issue:`25481`)
377-
-
377+
- Bug in incorrect ticklabel positions when plotting an index that are non-numeric / non-datetime (:issue:`7612` :issue:`15912` :issue:`22334`)
378378
-
379379
-
380380

pandas/plotting/_core.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ def _add_table(self):
401401

402402
def _post_plot_logic_common(self, ax, data):
403403
"""Common post process for each axes"""
404+
from matplotlib.ticker import FixedLocator, FixedFormatter
404405

405406
def get_label(i):
406407
try:
@@ -410,8 +411,12 @@ def get_label(i):
410411

411412
if self.orientation == 'vertical' or self.orientation is None:
412413
if self._need_to_set_index:
413-
xticklabels = [get_label(x) for x in ax.get_xticks()]
414+
xticks = ax.get_xticks()
415+
xticklabels = [get_label(x) for x in xticks]
414416
ax.set_xticklabels(xticklabels)
417+
ax.xaxis.set_major_locator(FixedLocator(xticks))
418+
ax.xaxis.set_major_formatter(FixedFormatter(xticklabels))
419+
415420
self._apply_axis_properties(ax.xaxis, rot=self.rot,
416421
fontsize=self.fontsize)
417422
self._apply_axis_properties(ax.yaxis, fontsize=self.fontsize)
@@ -422,8 +427,11 @@ def get_label(i):
422427

423428
elif self.orientation == 'horizontal':
424429
if self._need_to_set_index:
425-
yticklabels = [get_label(y) for y in ax.get_yticks()]
430+
yticks = ax.get_yticks()
431+
yticklabels = [get_label(y) for y in yticks]
426432
ax.set_yticklabels(yticklabels)
433+
ax.xaxis.set_major_locator(FixedLocator(yticks))
434+
ax.xaxis.set_major_formatter(FixedFormatter(yticklabels))
427435
self._apply_axis_properties(ax.yaxis, rot=self.rot,
428436
fontsize=self.fontsize)
429437
self._apply_axis_properties(ax.xaxis, fontsize=self.fontsize)

pandas/tests/plotting/test_frame.py

+34
Original file line numberDiff line numberDiff line change
@@ -2995,6 +2995,40 @@ def test_secondary_axis_font_size(self, method):
29952995
self._check_ticks_props(axes=ax.right_ax,
29962996
ylabelsize=fontsize)
29972997

2998+
@pytest.mark.slow
2999+
def test_x_string_values_ticks(self):
3000+
# Test if string plot index have a fixed xtick position
3001+
# GH: 7612, GH: 22334
3002+
df = pd.DataFrame({'sales': [3, 2, 3],
3003+
'visits': [20, 42, 28],
3004+
'day': ['Monday', 'Tuesday', 'Wednesday']})
3005+
ax = df.plot.area(x='day')
3006+
ax.set_xlim(-1, 3)
3007+
xticklabels = [t.get_text() for t in ax.get_xticklabels()]
3008+
labels_position = dict(zip(xticklabels, ax.get_xticks()))
3009+
# Testing if the label stayed at the right position
3010+
assert labels_position['Monday'] == 0.0
3011+
assert labels_position['Tuesday'] == 1.0
3012+
assert labels_position['Wednesday'] == 2.0
3013+
3014+
@pytest.mark.slow
3015+
def test_x_multiindex_values_ticks(self):
3016+
# Test if multiindex plot index have a fixed xtick position
3017+
# GH: 15912
3018+
index = pd.MultiIndex.from_product([[2012, 2013], [1, 2]])
3019+
df = pd.DataFrame(np.random.randn(4, 2),
3020+
columns=['A', 'B'],
3021+
index=index)
3022+
ax = df.plot()
3023+
ax.set_xlim(-1, 4)
3024+
xticklabels = [t.get_text() for t in ax.get_xticklabels()]
3025+
labels_position = dict(zip(xticklabels, ax.get_xticks()))
3026+
# Testing if the label stayed at the right position
3027+
assert labels_position['(2012, 1)'] == 0.0
3028+
assert labels_position['(2012, 2)'] == 1.0
3029+
assert labels_position['(2013, 1)'] == 2.0
3030+
assert labels_position['(2013, 2)'] == 3.0
3031+
29983032

29993033
def _generate_4_axes_via_gridspec():
30003034
import matplotlib.pyplot as plt

0 commit comments

Comments
 (0)