Skip to content

Commit 0aa598a

Browse files
authored
BUG: Fixes plotting with nullable integers (#32073) (#38014)
1 parent 292da03 commit 0aa598a

File tree

3 files changed

+41
-7
lines changed

3 files changed

+41
-7
lines changed

doc/source/whatsnew/v1.2.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,7 @@ Plotting
746746
indexed by a :class:`.TimedeltaIndex` with a fixed frequency and the x-axis lower limit was greater than the upper limit (:issue:`37454`)
747747
- Bug in :meth:`.DataFrameGroupBy.boxplot` when ``subplots=False`` would raise a ``KeyError`` (:issue:`16748`)
748748
- Bug in :meth:`DataFrame.plot` and :meth:`Series.plot` was overwriting matplotlib's shared y axes behaviour when no ``sharey`` parameter was passed (:issue:`37942`)
749+
- Bug in :meth:`DataFrame.plot` was raising a ``TypeError`` with ``ExtensionDtype`` columns (:issue:`32073`)
749750

750751

751752
Groupby/resample/rolling

pandas/plotting/_matplotlib/core.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
from pandas.util._decorators import cache_readonly
1010

1111
from pandas.core.dtypes.common import (
12+
is_extension_array_dtype,
1213
is_float,
14+
is_float_dtype,
1315
is_hashable,
1416
is_integer,
17+
is_integer_dtype,
1518
is_iterator,
1619
is_list_like,
1720
is_number,
@@ -383,6 +386,20 @@ def result(self):
383386
else:
384387
return self.axes[0]
385388

389+
def _convert_to_ndarray(self, data):
390+
# GH32073: cast to float if values contain nulled integers
391+
if (
392+
is_integer_dtype(data.dtype) or is_float_dtype(data.dtype)
393+
) and is_extension_array_dtype(data.dtype):
394+
return data.to_numpy(dtype="float", na_value=np.nan)
395+
396+
# GH25587: cast ExtensionArray of pandas (IntegerArray, etc.) to
397+
# np.ndarray before plot.
398+
if len(data) > 0:
399+
return np.asarray(data)
400+
401+
return data
402+
386403
def _compute_plot_data(self):
387404
data = self.data
388405

@@ -423,13 +440,7 @@ def _compute_plot_data(self):
423440
if is_empty:
424441
raise TypeError("no numeric data to plot")
425442

426-
# GH25587: cast ExtensionArray of pandas (IntegerArray, etc.) to
427-
# np.ndarray before plot.
428-
numeric_data = numeric_data.copy()
429-
for col in numeric_data:
430-
numeric_data[col] = np.asarray(numeric_data[col])
431-
432-
self.data = numeric_data
443+
self.data = numeric_data.apply(self._convert_to_ndarray)
433444

434445
def _make_plot(self):
435446
raise AbstractMethodError(self)

pandas/tests/plotting/frame/test_frame.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,28 @@ def test_plot(self):
149149
result = ax.axes
150150
assert result is axes[0]
151151

152+
def test_nullable_int_plot(self):
153+
# GH 32073
154+
dates = ["2008", "2009", None, "2011", "2012"]
155+
df = DataFrame(
156+
{
157+
"A": [1, 2, 3, 4, 5],
158+
"B": [1.0, 2.0, 3.0, 4.0, 5.0],
159+
"C": [7, 5, np.nan, 3, 2],
160+
"D": pd.to_datetime(dates, format="%Y"),
161+
"E": pd.to_datetime(dates, format="%Y", utc=True),
162+
},
163+
dtype=np.int64,
164+
)
165+
166+
_check_plot_works(df.plot, x="A", y="B")
167+
_check_plot_works(df[["A", "B"]].plot, x="A", y="B")
168+
_check_plot_works(df[["C", "A"]].plot, x="C", y="A") # nullable value on x-axis
169+
_check_plot_works(df[["A", "C"]].plot, x="A", y="C")
170+
_check_plot_works(df[["B", "C"]].plot, x="B", y="C")
171+
_check_plot_works(df[["A", "D"]].plot, x="A", y="D")
172+
_check_plot_works(df[["A", "E"]].plot, x="A", y="E")
173+
152174
def test_integer_array_plot(self):
153175
# GH 25587
154176
arr = integer_array([1, 2, 3, 4], dtype="UInt32")

0 commit comments

Comments
 (0)