TYP: plotting._matplotlib (#47311) · pandas-dev/pandas@696e9bd (original) (raw)

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:

`