Repository: pandas-dev/pandas
Pull request: BUG: Cast ExtensionArray to numpy ndarray before plot
Cast `ExtensionArray`(eg. `IntegerArray`) to `np.ndarray` before send to matplotlib to plot, fixes #25587.

- [x] closes #25587
- [x] tests added / passed
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [x] whatsnew entry


Problem statement:
plotting dtype "UInt32" fails
#### Code Sample, a copy-pastable example if possible

```python
import pandas as pd

s = pd.Series([ 4, 5, 3 ,2 ], dtype="UInt32")
s.astype("int32").plot() # succeeds
s.plot() # fails


```
fails with
```
Traceback (most recent call last):
  File "test_plot.py", line 7, in <module>
    s.plot()
  File "/nix/store/biq309lxqwpl1nfap4h3s58wcxd134xq-python3.7-pandas-0.24.1/lib/python3.7/site-packages/pandas/plotting/_core.py", line 2740, in __call__
    **kwds)
  File "/nix/store/biq309lxqwpl1nfap4h3s58wcxd134xq-python3.7-pandas-0.24.1/lib/python3.7/site-packages/pandas/plotting/_core.py", line 1995, in plot_series
    **kwds)
  File "/nix/store/biq309lxqwpl1nfap4h3s58wcxd134xq-python3.7-pandas-0.24.1/lib/python3.7/site-packages/pandas/plotting/_core.py", line 1798, in _plot
    plot_obj.generate()
  File "/nix/store/biq309lxqwpl1nfap4h3s58wcxd134xq-python3.7-pandas-0.24.1/lib/python3.7/site-packages/pandas/plotting/_core.py", line 251, in generate
    self._make_plot()
  File "/nix/store/biq309lxqwpl1nfap4h3s58wcxd134xq-python3.7-pandas-0.24.1/lib/python3.7/site-packages/pandas/plotting/_core.py", line 993, in _make_plot
    **kwds)
  File "/nix/store/biq309lxqwpl1nfap4h3s58wcxd134xq-python3.7-pandas-0.24.1/lib/python3.7/site-packages/pandas/plotting/_core.py", line 1008, in _plot
    lines = MPLPlot._plot(ax, x, y_values, style=style, **kwds)
  File "/nix/store/biq309lxqwpl1nfap4h3s58wcxd134xq-python3.7-pandas-0.24.1/lib/python3.7/site-packages/pandas/plotting/_core.py", line 598, in _plot
    return ax.plot(*args, **kwds)
  File "/nix/store/xgfsbxa29szyi30hl48hac1gihic3z3f-python3.7-matplotlib-3.0.3/lib/python3.7/site-packages/matplotlib/__init__.py", line 1810, in inner
    return func(ax, *args, **kwargs)
  File "/nix/store/xgfsbxa29szyi30hl48hac1gihic3z3f-python3.7-matplotlib-3.0.3/lib/python3.7/site-packages/matplotlib/axes/_axes.py", line 1611, in plot
    for line in self._get_lines(*args, **kwargs):
  File "/nix/store/xgfsbxa29szyi30hl48hac1gihic3z3f-python3.7-matplotlib-3.0.3/lib/python3.7/site-packages/matplotlib/axes/_base.py", line 393, in _grab_next_args
    yield from self._plot_args(this, kwargs)
  File "/nix/store/xgfsbxa29szyi30hl48hac1gihic3z3f-python3.7-matplotlib-3.0.3/lib/python3.7/site-packages/matplotlib/axes/_base.py", line 378, in _plot_args
    ncx, ncy = x.shape[1], y.shape[1]
IndexError: tuple index out of range
```


#### Problem description
When using the new type UInt32, plotting won't work.

#### Output of ``pd.show_versions()``

<details>

[paste the output of ``pd.show_versions()`` here below this line]
INSTALLED VERSIONS
------------------
commit: None
python: 3.7.2.final.0
python-bits: 64
OS: Linux
OS-release: 4.20.12
machine: x86_64
processor: 
byteorder: little
LC_ALL: None
LANG: C.UTF-8
LOCALE: None.None

pandas: 0+unknown
pytest: None
pip: 19.0.3
setuptools: 40.8.0
Cython: None
numpy: 1.16.1
scipy: 1.2.1
pyarrow: None
xarray: None
IPython: None
sphinx: None
patsy: None
dateutil: 2.8.0
pytz: 2018.9
blosc: None
bottleneck: 1.2.1
tables: 3.4.4
numexpr: 2.6.9
feather: None
matplotlib: 3.0.3
openpyxl: 2.6.0
xlrd: 1.2.0
xlwt: 1.3.0
xlsxwriter: None
lxml.etree: 4.3.1
bs4: 4.7.1
html5lib: 1.0.1
sqlalchemy: 1.2.14
pymysql: None
psycopg2: None
jinja2: None
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None
gcsfs: None

</details>

Hints from issue discussion:
pandas: 0+unknown, why is this?
it's pandas 0.24.1 with this commit applied on top https://github.com/pandas-dev/pandas/pull/25289. I haven't tried master but the bug should be valid for 0.24.1.
Thanks for the report. Let us know if you want to work on a fix for this. Something in matplotlib doesn't like extension arrays, which can't be reshaped to 2d arrays. We may need to convert before passing to mpl.

Commit message: Remove unused import.

Signed-off-by: HE, Tao <sighingnow@gmail.com>

Patch to review:
diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst
index 284943cf49070..3a114f629f631 100644
--- a/doc/source/whatsnew/v0.25.0.rst
+++ b/doc/source/whatsnew/v0.25.0.rst
@@ -122,7 +122,7 @@ Bug Fixes
 ~~~~~~~~~
 - Bug in :func:`to_datetime` which would raise an (incorrect) ``ValueError`` when called with a date far into the future and the ``format`` argument specified instead of raising ``OutOfBoundsDatetime`` (:issue:`23830`)
 - Bug in an error message in :meth:`DataFrame.plot`. Improved the error message if non-numerics are passed to :meth:`DataFrame.plot` (:issue:`25481`)
--
+- Fixed bug where :class:`api.extensions.ExtensionArray` could not be used in matplotlib plotting (:issue:`25587`)
 
 Categorical
 ^^^^^^^^^^^
diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py
index b9ec4d58db739..86390729167b2 100644
--- a/pandas/plotting/_core.py
+++ b/pandas/plotting/_core.py
@@ -365,7 +365,13 @@ def _compute_plot_data(self):
         if is_empty:
             raise TypeError('no numeric data to plot')
 
-        self.data = numeric_data
+        # GH25587: cast ExtensionArray of pandas (IntegerArray, etc.) to
+        # np.ndarray before plot.
+        numeric_data_np = numeric_data.copy()
+        for col in numeric_data:
+            numeric_data_np[col] = np.asarray(numeric_data[col])
+
+        self.data = numeric_data_np
 
     def _make_plot(self):
         raise AbstractMethodError(self)
@@ -1794,7 +1800,6 @@ def _plot(data, x=None, y=None, subplots=False,
                         )
                     label_name = label_kw or data.columns
                     data.columns = label_name
-
         plot_obj = klass(data, subplots=subplots, ax=ax, kind=kind, **kwds)
 
     plot_obj.generate()
diff --git a/pandas/tests/plotting/test_frame.py b/pandas/tests/plotting/test_frame.py
index 28806bb67c896..7346a3b09aecf 100644
--- a/pandas/tests/plotting/test_frame.py
+++ b/pandas/tests/plotting/test_frame.py
@@ -18,6 +18,7 @@
 import pandas as pd
 from pandas import (
     DataFrame, MultiIndex, PeriodIndex, Series, bdate_range, date_range)
+from pandas.core.arrays import integer_array
 from pandas.tests.plotting.common import (
     TestPlotBase, _check_plot_works, _ok_for_gaussian_kde,
     _skip_if_no_scipy_gaussian_kde)
@@ -144,8 +145,26 @@ def test_plot(self):
         result = ax.axes
         assert result is axes[0]
 
-    # GH 15516
+    def test_integer_array_plot(self):
+        # GH 25587
+        arr = integer_array([1, 2, 3, 4], dtype="UInt32")
+
+        s = Series(arr)
+        _check_plot_works(s.plot.line)
+        _check_plot_works(s.plot.bar)
+        _check_plot_works(s.plot.hist)
+        _check_plot_works(s.plot.pie)
+
+        df = DataFrame({'x': arr, 'y': arr})
+        _check_plot_works(df.plot.line)
+        _check_plot_works(df.plot.bar)
+        _check_plot_works(df.plot.hist)
+        _check_plot_works(df.plot.pie, y='y')
+        _check_plot_works(df.plot.scatter, x='x', y='y')
+        _check_plot_works(df.plot.hexbin, x='x', y='y')
+
     def test_mpl2_color_cycle_str(self):
+        # GH 15516
         colors = ['C' + str(x) for x in range(10)]
         df = DataFrame(randn(10, 3), columns=['a', 'b', 'c'])
         for c in colors:


Code review comments:
diff_hunk: @@ -365,7 +365,13 @@ def _compute_plot_data(self):
         if is_empty:
             raise TypeError('no numeric data to plot')
 
-        self.data = numeric_data
+        # GH25587: cast ExtensionArray of pandas (IntegerArray, etc.) to
+        # np.ndarray before plot.
+        numeric_data_np = numeric_data.copy()
path: pandas/plotting/_core.py
text: @user1:
you can just call this ``numeric_data``



@author:
Done.

diff_hunk: @@ -122,7 +122,7 @@ Bug Fixes
 ~~~~~~~~~
 - Bug in :func:`to_datetime` which would raise an (incorrect) ``ValueError`` when called with a date far into the future and the ``format`` argument specified instead of raising ``OutOfBoundsDatetime`` (:issue:`23830`)
 - Bug in an error message in :meth:`DataFrame.plot`. Improved the error message if non-numerics are passed to :meth:`DataFrame.plot` (:issue:`25481`)
--
+- Fixed bug where :class:`api.extensions.ExtensionArray` could not be used in matplotlib plotting (:issue:`25587`)
path: doc/source/whatsnew/v0.25.0.rst
text: @user1:
can you move this to plotting section (and the one above as well)

@author:
Done, that for reminding me the exists of that section in doc.