1
1
from __future__ import annotations
2
2
3
+ from abc import (
4
+ ABC ,
5
+ abstractmethod ,
6
+ )
3
7
from typing import (
4
8
TYPE_CHECKING ,
5
9
Hashable ,
6
10
Iterable ,
11
+ Literal ,
7
12
Sequence ,
8
13
)
9
14
import warnings
10
15
11
16
from matplotlib .artist import Artist
12
17
import numpy as np
13
18
14
- from pandas ._typing import IndexLabel
19
+ from pandas ._typing import (
20
+ IndexLabel ,
21
+ PlottingOrientation ,
22
+ )
15
23
from pandas .errors import AbstractMethodError
16
24
from pandas .util ._decorators import cache_readonly
17
25
@@ -78,7 +86,7 @@ def _color_in_style(style: str) -> bool:
78
86
return not set (BASE_COLORS ).isdisjoint (style )
79
87
80
88
81
- class MPLPlot :
89
+ class MPLPlot ( ABC ) :
82
90
"""
83
91
Base class for assembling a pandas plot using matplotlib
84
92
@@ -89,13 +97,17 @@ class MPLPlot:
89
97
"""
90
98
91
99
@property
92
- def _kind (self ):
100
+ @abstractmethod
101
+ def _kind (self ) -> str :
93
102
"""Specify kind str. Must be overridden in child class"""
94
103
raise NotImplementedError
95
104
96
105
_layout_type = "vertical"
97
106
_default_rot = 0
98
- orientation : str | None = None
107
+
108
+ @property
109
+ def orientation (self ) -> str | None :
110
+ return None
99
111
100
112
axes : np .ndarray # of Axes objects
101
113
@@ -843,7 +855,9 @@ def _get_xticks(self, convert_period: bool = False):
843
855
844
856
@classmethod
845
857
@register_pandas_matplotlib_converters
846
- def _plot (cls , ax : Axes , x , y , style = None , is_errorbar : bool = False , ** kwds ):
858
+ def _plot (
859
+ cls , ax : Axes , x , y : np .ndarray , style = None , is_errorbar : bool = False , ** kwds
860
+ ):
847
861
mask = isna (y )
848
862
if mask .any ():
849
863
y = np .ma .array (y )
@@ -1101,7 +1115,7 @@ def _get_axes_layout(self) -> tuple[int, int]:
1101
1115
return (len (y_set ), len (x_set ))
1102
1116
1103
1117
1104
- class PlanePlot (MPLPlot ):
1118
+ class PlanePlot (MPLPlot , ABC ):
1105
1119
"""
1106
1120
Abstract class for plotting on plane, currently scatter and hexbin.
1107
1121
"""
@@ -1159,7 +1173,9 @@ def _plot_colorbar(self, ax: Axes, **kwds):
1159
1173
1160
1174
1161
1175
class ScatterPlot (PlanePlot ):
1162
- _kind = "scatter"
1176
+ @property
1177
+ def _kind (self ) -> Literal ["scatter" ]:
1178
+ return "scatter"
1163
1179
1164
1180
def __init__ (self , data , x , y , s = None , c = None , ** kwargs ) -> None :
1165
1181
if s is None :
@@ -1247,7 +1263,9 @@ def _make_plot(self):
1247
1263
1248
1264
1249
1265
class HexBinPlot (PlanePlot ):
1250
- _kind = "hexbin"
1266
+ @property
1267
+ def _kind (self ) -> Literal ["hexbin" ]:
1268
+ return "hexbin"
1251
1269
1252
1270
def __init__ (self , data , x , y , C = None , ** kwargs ) -> None :
1253
1271
super ().__init__ (data , x , y , ** kwargs )
@@ -1277,9 +1295,15 @@ def _make_legend(self):
1277
1295
1278
1296
1279
1297
class LinePlot (MPLPlot ):
1280
- _kind = "line"
1281
1298
_default_rot = 0
1282
- orientation = "vertical"
1299
+
1300
+ @property
1301
+ def orientation (self ) -> PlottingOrientation :
1302
+ return "vertical"
1303
+
1304
+ @property
1305
+ def _kind (self ) -> Literal ["line" , "area" , "hist" , "kde" , "box" ]:
1306
+ return "line"
1283
1307
1284
1308
def __init__ (self , data , ** kwargs ) -> None :
1285
1309
from pandas .plotting import plot_params
@@ -1363,8 +1387,7 @@ def _plot( # type: ignore[override]
1363
1387
cls ._update_stacker (ax , stacking_id , y )
1364
1388
return lines
1365
1389
1366
- @classmethod
1367
- def _ts_plot (cls , ax : Axes , x , data , style = None , ** kwds ):
1390
+ def _ts_plot (self , ax : Axes , x , data , style = None , ** kwds ):
1368
1391
# accept x to be consistent with normal plot func,
1369
1392
# x is not passed to tsplot as it uses data.index as x coordinate
1370
1393
# column_num must be in kwds for stacking purpose
@@ -1377,9 +1400,9 @@ def _ts_plot(cls, ax: Axes, x, data, style=None, **kwds):
1377
1400
decorate_axes (ax .left_ax , freq , kwds )
1378
1401
if hasattr (ax , "right_ax" ):
1379
1402
decorate_axes (ax .right_ax , freq , kwds )
1380
- ax ._plot_data .append ((data , cls ._kind , kwds ))
1403
+ ax ._plot_data .append ((data , self ._kind , kwds ))
1381
1404
1382
- lines = cls ._plot (ax , data .index , data .values , style = style , ** kwds )
1405
+ lines = self ._plot (ax , data .index , data .values , style = style , ** kwds )
1383
1406
# set date formatter, locators and rescale limits
1384
1407
format_dateaxis (ax , ax .freq , data .index )
1385
1408
return lines
@@ -1471,7 +1494,9 @@ def get_label(i):
1471
1494
1472
1495
1473
1496
class AreaPlot (LinePlot ):
1474
- _kind = "area"
1497
+ @property
1498
+ def _kind (self ) -> Literal ["area" ]:
1499
+ return "area"
1475
1500
1476
1501
def __init__ (self , data , ** kwargs ) -> None :
1477
1502
kwargs .setdefault ("stacked" , True )
@@ -1544,9 +1569,15 @@ def _post_plot_logic(self, ax: Axes, data):
1544
1569
1545
1570
1546
1571
class BarPlot (MPLPlot ):
1547
- _kind = "bar"
1572
+ @property
1573
+ def _kind (self ) -> Literal ["bar" , "barh" ]:
1574
+ return "bar"
1575
+
1548
1576
_default_rot = 90
1549
- orientation = "vertical"
1577
+
1578
+ @property
1579
+ def orientation (self ) -> PlottingOrientation :
1580
+ return "vertical"
1550
1581
1551
1582
def __init__ (self , data , ** kwargs ) -> None :
1552
1583
# we have to treat a series differently than a
@@ -1698,9 +1729,15 @@ def _decorate_ticks(self, ax: Axes, name, ticklabels, start_edge, end_edge):
1698
1729
1699
1730
1700
1731
class BarhPlot (BarPlot ):
1701
- _kind = "barh"
1732
+ @property
1733
+ def _kind (self ) -> Literal ["barh" ]:
1734
+ return "barh"
1735
+
1702
1736
_default_rot = 0
1703
- orientation = "horizontal"
1737
+
1738
+ @property
1739
+ def orientation (self ) -> Literal ["horizontal" ]:
1740
+ return "horizontal"
1704
1741
1705
1742
@property
1706
1743
def _start_base (self ):
@@ -1727,7 +1764,10 @@ def _decorate_ticks(self, ax: Axes, name, ticklabels, start_edge, end_edge):
1727
1764
1728
1765
1729
1766
class PiePlot (MPLPlot ):
1730
- _kind = "pie"
1767
+ @property
1768
+ def _kind (self ) -> Literal ["pie" ]:
1769
+ return "pie"
1770
+
1731
1771
_layout_type = "horizontal"
1732
1772
1733
1773
def __init__ (self , data , kind = None , ** kwargs ) -> None :
0 commit comments