Skip to content

Commit 62a0ebc

Browse files
javadnoorbjreback
authored andcommitted
scatter plot and hexbin plot lose x-axis when colorbar is included. (#20446)
1 parent 7bb010c commit 62a0ebc

File tree

3 files changed

+73
-7
lines changed

3 files changed

+73
-7
lines changed

doc/source/whatsnew/v0.24.0.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ I/O
336336
Plotting
337337
^^^^^^^^
338338

339-
-
339+
- Bug in :func:'DataFrame.plot.scatter' and :func:'DataFrame.plot.hexbin' caused x-axis label and ticklabels to disappear when colorbar was on in IPython inline backend (:issue:`10611` and :issue:`10678`)
340340
-
341341
-
342342

pandas/plotting/_core.py

+29-6
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,32 @@ def _post_plot_logic(self, ax, data):
833833
ax.set_ylabel(pprint_thing(y))
834834
ax.set_xlabel(pprint_thing(x))
835835

836+
def _plot_colorbar(self, ax, **kwds):
837+
# Addresses issues #10611 and #10678:
838+
# When plotting scatterplots and hexbinplots in IPython
839+
# inline backend the colorbar axis height tends not to
840+
# exactly match the parent axis height.
841+
# The difference is due to small fractional differences
842+
# in floating points with similar representation.
843+
# To deal with this, this method forces the colorbar
844+
# height to take the height of the parent axes.
845+
# For a more detailed description of the issue
846+
# see the following link:
847+
# https://github.com/ipython/ipython/issues/11215
848+
849+
img = ax.collections[0]
850+
cbar = self.fig.colorbar(img, **kwds)
851+
points = ax.get_position().get_points()
852+
cbar_points = cbar.ax.get_position().get_points()
853+
cbar.ax.set_position([cbar_points[0, 0],
854+
points[0, 1],
855+
cbar_points[1, 0] - cbar_points[0, 0],
856+
points[1, 1] - points[0, 1]])
857+
# To see the discrepancy in axis heights uncomment
858+
# the following two lines:
859+
# print(points[1, 1] - points[0, 1])
860+
# print(cbar_points[1, 1] - cbar_points[0, 1])
861+
836862

837863
class ScatterPlot(PlanePlot):
838864
_kind = 'scatter'
@@ -878,11 +904,9 @@ def _make_plot(self):
878904
scatter = ax.scatter(data[x].values, data[y].values, c=c_values,
879905
label=label, cmap=cmap, **self.kwds)
880906
if cb:
881-
img = ax.collections[0]
882-
kws = dict(ax=ax)
883907
if self.mpl_ge_1_3_1():
884-
kws['label'] = c if c_is_column else ''
885-
self.fig.colorbar(img, **kws)
908+
cbar_label = c if c_is_column else ''
909+
self._plot_colorbar(ax, label=cbar_label)
886910

887911
if label is not None:
888912
self._add_legend_handle(scatter, label)
@@ -923,8 +947,7 @@ def _make_plot(self):
923947
ax.hexbin(data[x].values, data[y].values, C=c_values, cmap=cmap,
924948
**self.kwds)
925949
if cb:
926-
img = ax.collections[0]
927-
self.fig.colorbar(img, ax=ax)
950+
self._plot_colorbar(ax)
928951

929952
def _make_legend(self):
930953
pass

pandas/tests/plotting/test_frame.py

+43
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,49 @@ def test_plot_scatter(self):
10891089
axes = df.plot(x='x', y='y', kind='scatter', subplots=True)
10901090
self._check_axes_shape(axes, axes_num=1, layout=(1, 1))
10911091

1092+
@pytest.mark.slow
1093+
def test_if_scatterplot_colorbar_affects_xaxis_visibility(self):
1094+
# addressing issue #10611, to ensure colobar does not
1095+
# interfere with x-axis label and ticklabels with
1096+
# ipython inline backend.
1097+
random_array = np.random.random((1000, 3))
1098+
df = pd.DataFrame(random_array,
1099+
columns=['A label', 'B label', 'C label'])
1100+
1101+
ax1 = df.plot.scatter(x='A label', y='B label')
1102+
ax2 = df.plot.scatter(x='A label', y='B label', c='C label')
1103+
1104+
vis1 = [vis.get_visible() for vis in
1105+
ax1.xaxis.get_minorticklabels()]
1106+
vis2 = [vis.get_visible() for vis in
1107+
ax2.xaxis.get_minorticklabels()]
1108+
assert vis1 == vis2
1109+
1110+
vis1 = [vis.get_visible() for vis in
1111+
ax1.xaxis.get_majorticklabels()]
1112+
vis2 = [vis.get_visible() for vis in
1113+
ax2.xaxis.get_majorticklabels()]
1114+
assert vis1 == vis2
1115+
1116+
assert (ax1.xaxis.get_label().get_visible() ==
1117+
ax2.xaxis.get_label().get_visible())
1118+
1119+
@pytest.mark.slow
1120+
def test_if_hexbin_xaxis_label_is_visible(self):
1121+
# addressing issue #10678, to ensure colobar does not
1122+
# interfere with x-axis label and ticklabels with
1123+
# ipython inline backend.
1124+
random_array = np.random.random((1000, 3))
1125+
df = pd.DataFrame(random_array,
1126+
columns=['A label', 'B label', 'C label'])
1127+
1128+
ax = df.plot.hexbin('A label', 'B label', gridsize=12)
1129+
assert all([vis.get_visible() for vis in
1130+
ax.xaxis.get_minorticklabels()])
1131+
assert all([vis.get_visible() for vis in
1132+
ax.xaxis.get_majorticklabels()])
1133+
assert ax.xaxis.get_label().get_visible()
1134+
10921135
@pytest.mark.slow
10931136
def test_plot_scatter_with_categorical_data(self):
10941137
# GH 16199

0 commit comments

Comments
 (0)