1from __future__ import annotations
2
3import importlib
4from typing import (
5 TYPE_CHECKING,
6 Literal,
7)
8
9from pandas._config import get_option
10
11from pandas.util._decorators import set_module
12
13from pandas.core.dtypes.common import (
14 is_integer,
15 is_list_like,
16)
17from pandas.core.dtypes.generic import (
18 ABCDataFrame,
19 ABCSeries,
20)
21
22from pandas.core.base import PandasObject
23
24if TYPE_CHECKING:
25 from collections.abc import (
26 Callable,
27 Hashable,
28 Sequence,
29 )
30 import types
31
32 from matplotlib.axes import Axes
33 import numpy as np
34
35 from pandas._typing import IndexLabel
36
37 from pandas import (
38 DataFrame,
39 Index,
40 Series,
41 )
42 from pandas.core.groupby.generic import DataFrameGroupBy
43
44
45def holds_integer(column: Index) -> bool:
46 return column.dtype.kind in "iu"
47
48
49@set_module("pandas.plotting")
50def hist_series(
51 self: Series,
52 by=None,
53 ax=None,
54 grid: bool = True,
55 xlabelsize: int | None = None,
56 xrot: float | None = None,
57 ylabelsize: int | None = None,
58 yrot: float | None = None,
59 figsize: tuple[int, int] | None = None,
60 bins: int | Sequence[int] = 10,
61 backend: str | None = None,
62 legend: bool = False,
63 **kwargs,
64):
65 """
66 Draw histogram of the input series using matplotlib.
67
68 Parameters
69 ----------
70 by : object, optional
71 If passed, then used to form histograms for separate groups.
72 ax : matplotlib axis object
73 If not passed, uses gca().
74 grid : bool, default True
75 Whether to show axis grid lines.
76 xlabelsize : int, default None
77 If specified changes the x-axis label size.
78 xrot : float, default None
79 Rotation of x axis labels.
80 ylabelsize : int, default None
81 If specified changes the y-axis label size.
82 yrot : float, default None
83 Rotation of y axis labels.
84 figsize : tuple, default None
85 Figure size in inches by default.
86 bins : int or sequence, default 10
87 Number of histogram bins to be used. If an integer is given, bins + 1
88 bin edges are calculated and returned. If bins is a sequence, gives
89 bin edges, including left edge of first bin and right edge of last
90 bin. In this case, bins is returned unmodified.
91 backend : str, default None
92 Backend to use instead of the backend specified in the option
93 ``plotting.backend``. For instance, 'matplotlib'. Alternatively, to
94 specify the ``plotting.backend`` for the whole session, set
95 ``pd.options.plotting.backend``.
96 legend : bool, default False
97 Whether to show the legend.
98
99 **kwargs
100 To be passed to the actual plotting function.
101
102 Returns
103 -------
104 matplotlib.axes.Axes
105 A histogram plot.
106
107 See Also
108 --------
109 matplotlib.axes.Axes.hist : Plot a histogram using matplotlib.
110
111 Examples
112 --------
113 For Series:
114
115 .. plot::
116 :context: close-figs
117
118 >>> lst = ["a", "a", "a", "b", "b", "b"]
119 >>> ser = pd.Series([1, 2, 2, 4, 6, 6], index=lst)
120 >>> hist = ser.hist()
121
122 For Groupby:
123
124 .. plot::
125 :context: close-figs
126
127 >>> lst = ["a", "a", "a", "b", "b", "b"]
128 >>> ser = pd.Series([1, 2, 2, 4, 6, 6], index=lst)
129 >>> hist = ser.groupby(level=0).hist()
130 """
131 plot_backend = _get_plot_backend(backend)
132 return plot_backend.hist_series(
133 self,
134 by=by,
135 ax=ax,
136 grid=grid,
137 xlabelsize=xlabelsize,
138 xrot=xrot,
139 ylabelsize=ylabelsize,
140 yrot=yrot,
141 figsize=figsize,
142 bins=bins,
143 legend=legend,
144 **kwargs,
145 )
146
147
148@set_module("pandas.plotting")
149def hist_frame(
150 data: DataFrame,
151 column: IndexLabel | None = None,
152 by=None,
153 grid: bool = True,
154 xlabelsize: int | None = None,
155 xrot: float | None = None,
156 ylabelsize: int | None = None,
157 yrot: float | None = None,
158 ax=None,
159 sharex: bool = False,
160 sharey: bool = False,
161 figsize: tuple[int, int] | None = None,
162 layout: tuple[int, int] | None = None,
163 bins: int | Sequence[int] = 10,
164 backend: str | None = None,
165 legend: bool = False,
166 **kwargs,
167):
168 """
169 Make a histogram of the DataFrame's columns.
170
171 A `histogram`_ is a representation of the distribution of data.
172 This function calls :meth:`matplotlib.pyplot.hist`, on each series in
173 the DataFrame, resulting in one histogram per column.
174
175 .. _histogram: https://en.wikipedia.org/wiki/Histogram
176
177 Parameters
178 ----------
179 data : DataFrame
180 The pandas object holding the data.
181 column : str or sequence, optional
182 If passed, will be used to limit data to a subset of columns.
183 by : object, optional
184 If passed, then used to form histograms for separate groups.
185 grid : bool, default True
186 Whether to show axis grid lines.
187 xlabelsize : int, default None
188 If specified changes the x-axis label size.
189 xrot : float, default None
190 Rotation of x axis labels. For example, a value of 90 displays the
191 x labels rotated 90 degrees clockwise.
192 ylabelsize : int, default None
193 If specified changes the y-axis label size.
194 yrot : float, default None
195 Rotation of y axis labels. For example, a value of 90 displays the
196 y labels rotated 90 degrees clockwise.
197 ax : Matplotlib axes object, default None
198 The axes to plot the histogram on.
199 sharex : bool, default True if ax is None else False
200 In case subplots=True, share x axis and set some x axis labels to
201 invisible; defaults to True if ax is None otherwise False if an ax
202 is passed in.
203 Note that passing in both an ax and sharex=True will alter all x axis
204 labels for all subplots in a figure.
205 sharey : bool, default False
206 In case subplots=True, share y axis and set some y axis labels to
207 invisible.
208 figsize : tuple, optional
209 The size in inches of the figure to create. Uses the value in
210 `matplotlib.rcParams` by default.
211 layout : tuple, optional
212 Tuple of (rows, columns) for the layout of the histograms.
213 bins : int or sequence, default 10
214 Number of histogram bins to be used. If an integer is given, bins + 1
215 bin edges are calculated and returned. If bins is a sequence, gives
216 bin edges, including left edge of first bin and right edge of last
217 bin. In this case, bins is returned unmodified.
218
219 backend : str, default None
220 Backend to use instead of the backend specified in the option
221 ``plotting.backend``. For instance, 'matplotlib'. Alternatively, to
222 specify the ``plotting.backend`` for the whole session, set
223 ``pd.options.plotting.backend``.
224
225 legend : bool, default False
226 Whether to show the legend.
227
228 **kwargs
229 All other plotting keyword arguments to be passed to
230 :meth:`matplotlib.pyplot.hist`.
231
232 Returns
233 -------
234 np.ndarray
235 2D NumPy Array of :class:`matplotlib.axes.Axes`.
236
237 See Also
238 --------
239 matplotlib.pyplot.hist : Plot a histogram using matplotlib.
240
241 Examples
242 --------
243 This example draws a histogram based on the length and width of
244 some animals, displayed in three bins
245
246 .. plot::
247 :context: close-figs
248
249 >>> data = {
250 ... "length": [1.5, 0.5, 1.2, 0.9, 3],
251 ... "width": [0.7, 0.2, 0.15, 0.2, 1.1],
252 ... }
253 >>> index = ["pig", "rabbit", "duck", "chicken", "horse"]
254 >>> df = pd.DataFrame(data, index=index)
255 >>> hist = df.hist(bins=3)
256 """
257 plot_backend = _get_plot_backend(backend)
258 return plot_backend.hist_frame(
259 data,
260 column=column,
261 by=by,
262 grid=grid,
263 xlabelsize=xlabelsize,
264 xrot=xrot,
265 ylabelsize=ylabelsize,
266 yrot=yrot,
267 ax=ax,
268 sharex=sharex,
269 sharey=sharey,
270 figsize=figsize,
271 layout=layout,
272 legend=legend,
273 bins=bins,
274 **kwargs,
275 )
276
277
278@set_module("pandas.plotting")
279def boxplot(
280 data: DataFrame,
281 column: str | list[str] | None = None,
282 by: str | list[str] | None = None,
283 ax: Axes | None = None,
284 fontsize: float | str | None = None,
285 rot: int = 0,
286 grid: bool = True,
287 figsize: tuple[float, float] | None = None,
288 layout: tuple[int, int] | None = None,
289 return_type: str | None = None,
290 **kwargs,
291):
292 """
293 Make a box plot from DataFrame columns.
294
295 Make a box-and-whisker plot from DataFrame columns, optionally grouped
296 by some other columns. A box plot is a method for graphically depicting
297 groups of numerical data through their quartiles.
298 The box extends from the Q1 to Q3 quartile values of the data,
299 with a line at the median (Q2). The whiskers extend from the edges
300 of box to show the range of the data. By default, they extend no more than
301 `1.5 * IQR (IQR = Q3 - Q1)` from the edges of the box, ending at the farthest
302 data point within that interval. Outliers are plotted as separate dots.
303
304 For further details see
305 Wikipedia's entry for `boxplot <https://en.wikipedia.org/wiki/Box_plot>`_.
306
307 Parameters
308 ----------
309 data : DataFrame
310 The data to visualize.
311 column : str or list of str, optional
312 Column name or list of names, or vector.
313 Can be any valid input to :meth:`pandas.DataFrame.groupby`.
314 by : str or array-like, optional
315 Column in the DataFrame to :meth:`pandas.DataFrame.groupby`.
316 One box-plot will be done per value of columns in `by`.
317 ax : object of class matplotlib.axes.Axes, optional
318 The matplotlib axes to be used by boxplot.
319 fontsize : float or str
320 Tick label font size in points or as a string (e.g., `large`).
321 rot : float, default 0
322 The rotation angle of labels (in degrees)
323 with respect to the screen coordinate system.
324 grid : bool, default True
325 Setting this to True will show the grid.
326 figsize : A tuple (width, height) in inches
327 The size of the figure to create in matplotlib.
328 layout : tuple (rows, columns), optional
329 For example, (3, 5) will display the subplots
330 using 3 rows and 5 columns, starting from the top-left.
331 return_type : {'axes', 'dict', 'both'} or None, default 'axes'
332 The kind of object to return. The default is ``axes``.
333
334 * 'axes' returns the matplotlib axes the boxplot is drawn on.
335 * 'dict' returns a dictionary whose values are the matplotlib
336 lines of the boxplot.
337 * 'both' returns a namedtuple with the axes and dict.
338 * when grouping with ``by``, a Series mapping columns to
339 ``return_type`` is returned.
340
341 If ``return_type`` is `None`, a NumPy array
342 of axes with the same shape as ``layout`` is returned.
343
344 **kwargs
345 All other plotting keyword arguments to be passed to
346 :func:`matplotlib.pyplot.boxplot`.
347
348 Returns
349 -------
350 result
351 See Notes.
352
353 See Also
354 --------
355 Series.plot.hist: Make a histogram.
356 matplotlib.pyplot.boxplot : Matplotlib equivalent plot.
357
358 Notes
359 -----
360 The return type depends on the `return_type` parameter:
361
362 * 'axes' : object of class matplotlib.axes.Axes
363 * 'dict' : dict of matplotlib.lines.Line2D objects
364 * 'both' : a namedtuple with structure (ax, lines)
365
366 For data grouped with ``by``, return a Series of the above or a numpy
367 array:
368
369 * :class:`~pandas.Series`
370 * :class:`~numpy.array` (for ``return_type = None``)
371
372 Use ``return_type='dict'`` when you want to tweak the appearance
373 of the lines after plotting. In this case a dict containing the Lines
374 making up the boxes, caps, fliers, medians, and whiskers is returned.
375
376 Examples
377 --------
378
379 Boxplots can be created for every column in the dataframe
380 by ``df.boxplot()`` or indicating the columns to be used:
381
382 .. plot::
383 :context: close-figs
384
385 >>> np.random.seed(1234)
386 >>> df = pd.DataFrame(
387 ... np.random.randn(10, 4), columns=["Col1", "Col2", "Col3", "Col4"]
388 ... )
389 >>> boxplot = df.boxplot(column=["Col1", "Col2", "Col3"]) # doctest: +SKIP
390
391 Boxplots of variables distributions grouped by the values of a third
392 variable can be created using the option ``by``. For instance:
393
394 .. plot::
395 :context: close-figs
396
397 >>> df = pd.DataFrame(np.random.randn(10, 2), columns=["Col1", "Col2"])
398 >>> df["X"] = pd.Series(["A", "A", "A", "A", "A", "B", "B", "B", "B", "B"])
399 >>> boxplot = df.boxplot(by="X")
400
401 A list of strings (i.e. ``['X', 'Y']``) can be passed to boxplot
402 in order to group the data by combination of the variables in the x-axis:
403
404 .. plot::
405 :context: close-figs
406
407 >>> df = pd.DataFrame(np.random.randn(10, 3), columns=["Col1", "Col2", "Col3"])
408 >>> df["X"] = pd.Series(["A", "A", "A", "A", "A", "B", "B", "B", "B", "B"])
409 >>> df["Y"] = pd.Series(["A", "B", "A", "B", "A", "B", "A", "B", "A", "B"])
410 >>> boxplot = df.boxplot(column=["Col1", "Col2"], by=["X", "Y"])
411
412 The layout of boxplot can be adjusted giving a tuple to ``layout``:
413
414 .. plot::
415 :context: close-figs
416
417 >>> boxplot = df.boxplot(column=["Col1", "Col2"], by="X", layout=(2, 1))
418
419 Additional formatting can be done to the boxplot, like suppressing the grid
420 (``grid=False``), rotating the labels in the x-axis (i.e. ``rot=45``)
421 or changing the fontsize (i.e. ``fontsize=15``):
422
423 .. plot::
424 :context: close-figs
425
426 >>> boxplot = df.boxplot(grid=False, rot=45, fontsize=15) # doctest: +SKIP
427
428 The parameter ``return_type`` can be used to select the type of element
429 returned by `boxplot`. When ``return_type='axes'`` is selected,
430 the matplotlib axes on which the boxplot is drawn are returned:
431
432 >>> boxplot = df.boxplot(column=["Col1", "Col2"], return_type="axes")
433 >>> type(boxplot)
434 <class 'matplotlib.axes._axes.Axes'>
435
436 When grouping with ``by``, a Series mapping columns to ``return_type``
437 is returned:
438
439 >>> boxplot = df.boxplot(column=["Col1", "Col2"], by="X", return_type="axes")
440 >>> type(boxplot)
441 <class 'pandas.Series'>
442
443 If ``return_type`` is `None`, a NumPy array of axes with the same shape
444 as ``layout`` is returned:
445
446 >>> boxplot = df.boxplot(column=["Col1", "Col2"], by="X", return_type=None)
447 >>> type(boxplot)
448 <class 'numpy.ndarray'>
449 """
450 plot_backend = _get_plot_backend("matplotlib")
451 return plot_backend.boxplot(
452 data,
453 column=column,
454 by=by,
455 ax=ax,
456 fontsize=fontsize,
457 rot=rot,
458 grid=grid,
459 figsize=figsize,
460 layout=layout,
461 return_type=return_type,
462 **kwargs,
463 )
464
465
466@set_module("pandas.plotting")
467def boxplot_frame(
468 self: DataFrame,
469 column=None,
470 by=None,
471 ax=None,
472 fontsize: int | None = None,
473 rot: int = 0,
474 grid: bool = True,
475 figsize: tuple[float, float] | None = None,
476 layout=None,
477 return_type=None,
478 backend=None,
479 **kwargs,
480):
481 """
482 Make a box plot from DataFrame columns.
483
484 Make a box-and-whisker plot from DataFrame columns, optionally grouped
485 by some other columns. A box plot is a method for graphically depicting
486 groups of numerical data through their quartiles.
487 The box extends from the Q1 to Q3 quartile values of the data,
488 with a line at the median (Q2). The whiskers extend from the edges
489 of box to show the range of the data. By default, they extend no more than
490 `1.5 * IQR (IQR = Q3 - Q1)` from the edges of the box, ending at the farthest
491 data point within that interval. Outliers are plotted as separate dots.
492
493 For further details see
494 Wikipedia's entry for `boxplot <https://en.wikipedia.org/wiki/Box_plot>`_.
495
496 Parameters
497 ----------
498 column : str or list of str, optional
499 Column name or list of names, or vector.
500 Can be any valid input to :meth:`pandas.DataFrame.groupby`.
501 by : str or array-like, optional
502 Column in the DataFrame to :meth:`pandas.DataFrame.groupby`.
503 One box-plot will be done per value of columns in `by`.
504 ax : object of class matplotlib.axes.Axes, optional
505 The matplotlib axes to be used by boxplot.
506 fontsize : float or str
507 Tick label font size in points or as a string (e.g., `large`).
508 rot : float, default 0
509 The rotation angle of labels (in degrees)
510 with respect to the screen coordinate system.
511 grid : bool, default True
512 Setting this to True will show the grid.
513 figsize : A tuple (width, height) in inches
514 The size of the figure to create in matplotlib.
515 layout : tuple (rows, columns), optional
516 For example, (3, 5) will display the subplots
517 using 3 rows and 5 columns, starting from the top-left.
518 return_type : {'axes', 'dict', 'both'} or None, default 'axes'
519 The kind of object to return. The default is ``axes``.
520
521 * 'axes' returns the matplotlib axes the boxplot is drawn on.
522 * 'dict' returns a dictionary whose values are the matplotlib
523 lines of the boxplot.
524 * 'both' returns a namedtuple with the axes and dict.
525 * when grouping with ``by``, a Series mapping columns to
526 ``return_type`` is returned.
527
528 If ``return_type`` is `None`, a NumPy array
529 of axes with the same shape as ``layout`` is returned.
530 backend : str, default None
531 Backend to use instead of the backend specified in the option
532 ``plotting.backend``. For instance, 'matplotlib'. Alternatively, to
533 specify the ``plotting.backend`` for the whole session, set
534 ``pd.options.plotting.backend``.
535
536 **kwargs
537 All other plotting keyword arguments to be passed to
538 :func:`matplotlib.pyplot.boxplot`.
539
540 Returns
541 -------
542 result
543 See Notes.
544
545 See Also
546 --------
547 Series.plot.hist: Make a histogram.
548 matplotlib.pyplot.boxplot : Matplotlib equivalent plot.
549
550 Notes
551 -----
552 The return type depends on the `return_type` parameter:
553
554 * 'axes' : object of class matplotlib.axes.Axes
555 * 'dict' : dict of matplotlib.lines.Line2D objects
556 * 'both' : a namedtuple with structure (ax, lines)
557
558 For data grouped with ``by``, return a Series of the above or a numpy
559 array:
560
561 * :class:`~pandas.Series`
562 * :class:`~numpy.array` (for ``return_type = None``)
563
564 Use ``return_type='dict'`` when you want to tweak the appearance
565 of the lines after plotting. In this case a dict containing the Lines
566 making up the boxes, caps, fliers, medians, and whiskers is returned.
567
568 Examples
569 --------
570
571 Boxplots can be created for every column in the dataframe
572 by ``df.boxplot()`` or indicating the columns to be used:
573
574 .. plot::
575 :context: close-figs
576
577 >>> np.random.seed(1234)
578 >>> df = pd.DataFrame(
579 ... np.random.randn(10, 4), columns=["Col1", "Col2", "Col3", "Col4"]
580 ... )
581 >>> boxplot = df.boxplot(column=["Col1", "Col2", "Col3"]) # doctest: +SKIP
582
583 Boxplots of variables distributions grouped by the values of a third
584 variable can be created using the option ``by``. For instance:
585
586 .. plot::
587 :context: close-figs
588
589 >>> df = pd.DataFrame(np.random.randn(10, 2), columns=["Col1", "Col2"])
590 >>> df["X"] = pd.Series(["A", "A", "A", "A", "A", "B", "B", "B", "B", "B"])
591 >>> boxplot = df.boxplot(by="X")
592
593 A list of strings (i.e. ``['X', 'Y']``) can be passed to boxplot
594 in order to group the data by combination of the variables in the x-axis:
595
596 .. plot::
597 :context: close-figs
598
599 >>> df = pd.DataFrame(np.random.randn(10, 3), columns=["Col1", "Col2", "Col3"])
600 >>> df["X"] = pd.Series(["A", "A", "A", "A", "A", "B", "B", "B", "B", "B"])
601 >>> df["Y"] = pd.Series(["A", "B", "A", "B", "A", "B", "A", "B", "A", "B"])
602 >>> boxplot = df.boxplot(column=["Col1", "Col2"], by=["X", "Y"])
603
604 The layout of boxplot can be adjusted giving a tuple to ``layout``:
605
606 .. plot::
607 :context: close-figs
608
609 >>> boxplot = df.boxplot(column=["Col1", "Col2"], by="X", layout=(2, 1))
610
611 Additional formatting can be done to the boxplot, like suppressing the grid
612 (``grid=False``), rotating the labels in the x-axis (i.e. ``rot=45``)
613 or changing the fontsize (i.e. ``fontsize=15``):
614
615 .. plot::
616 :context: close-figs
617
618 >>> boxplot = df.boxplot(grid=False, rot=45, fontsize=15) # doctest: +SKIP
619
620 The parameter ``return_type`` can be used to select the type of element
621 returned by `boxplot`. When ``return_type='axes'`` is selected,
622 the matplotlib axes on which the boxplot is drawn are returned:
623
624 .. plot::
625 :context: close-figs
626
627 >>> boxplot = df.boxplot(column=["Col1", "Col2"], return_type="axes")
628 >>> type(boxplot)
629 <class 'matplotlib.axes._axes.Axes'>
630
631 When grouping with ``by``, a Series mapping columns to ``return_type``
632 is returned:
633
634 .. plot::
635 :context: close-figs
636
637 >>> boxplot = df.boxplot(column=["Col1", "Col2"], by="X", return_type="axes")
638 >>> type(boxplot)
639 <class 'pandas.Series'>
640
641 If ``return_type`` is `None`, a NumPy array of axes with the same shape
642 as ``layout`` is returned:
643
644 .. plot::
645 :context: close-figs
646
647 >>> boxplot = df.boxplot(column=["Col1", "Col2"], by="X", return_type=None)
648 >>> type(boxplot)
649 <class 'numpy.ndarray'>
650 """
651
652 plot_backend = _get_plot_backend(backend)
653 return plot_backend.boxplot_frame(
654 self,
655 column=column,
656 by=by,
657 ax=ax,
658 fontsize=fontsize,
659 rot=rot,
660 grid=grid,
661 figsize=figsize,
662 layout=layout,
663 return_type=return_type,
664 **kwargs,
665 )
666
667
668@set_module("pandas.plotting")
669def boxplot_frame_groupby(
670 grouped: DataFrameGroupBy,
671 subplots: bool = True,
672 column=None,
673 fontsize: int | None = None,
674 rot: int = 0,
675 grid: bool = True,
676 ax=None,
677 figsize: tuple[float, float] | None = None,
678 layout=None,
679 sharex: bool = False,
680 sharey: bool = True,
681 backend=None,
682 **kwargs,
683):
684 """
685 Make box plots from DataFrameGroupBy data.
686
687 Parameters
688 ----------
689 grouped : DataFrameGroupBy
690 The grouped DataFrame object over which to create the box plots.
691 subplots : bool
692 * ``False`` - no subplots will be used
693 * ``True`` - create a subplot for each group.
694 column : column name or list of names, or vector
695 Can be any valid input to groupby.
696 fontsize : float or str
697 Font size for the labels.
698 rot : float
699 Rotation angle of labels (in degrees) on the x-axis.
700 grid : bool
701 Whether to show grid lines on the plot.
702 ax : Matplotlib axis object, default None
703 The axes on which to draw the plots. If None, uses the current axes.
704 figsize : tuple of (float, float)
705 The figure size in inches (width, height).
706 layout : tuple (optional)
707 The layout of the plot: (rows, columns).
708 sharex : bool, default False
709 Whether x-axes will be shared among subplots.
710 sharey : bool, default True
711 Whether y-axes will be shared among subplots.
712 backend : str, default None
713 Backend to use instead of the backend specified in the option
714 ``plotting.backend``. For instance, 'matplotlib'. Alternatively, to
715 specify the ``plotting.backend`` for the whole session, set
716 ``pd.options.plotting.backend``.
717 **kwargs
718 All other plotting keyword arguments to be passed to
719 matplotlib's boxplot function.
720
721 Returns
722 -------
723 dict or DataFrame.boxplot return value
724 If ``subplots=True``, returns a dictionary of group keys to the boxplot
725 return values. If ``subplots=False``, returns the boxplot return value
726 of a single DataFrame.
727
728 See Also
729 --------
730 DataFrame.boxplot : Create a box plot from a DataFrame.
731 Series.plot : Plot a Series.
732
733 Examples
734 --------
735 You can create boxplots for grouped data and show them as separate subplots:
736
737 .. plot::
738 :context: close-figs
739
740 >>> import itertools
741 >>> tuples = [t for t in itertools.product(range(1000), range(4))]
742 >>> index = pd.MultiIndex.from_tuples(tuples, names=["lvl0", "lvl1"])
743 >>> data = np.random.randn(len(index), 4)
744 >>> df = pd.DataFrame(data, columns=list("ABCD"), index=index)
745 >>> grouped = df.groupby(level="lvl1")
746 >>> grouped.boxplot(rot=45, fontsize=12, figsize=(8, 10)) # doctest: +SKIP
747
748 The ``subplots=False`` option shows the boxplots in a single figure.
749
750 .. plot::
751 :context: close-figs
752
753 >>> grouped.boxplot(subplots=False, rot=45, fontsize=12) # doctest: +SKIP
754 """
755 plot_backend = _get_plot_backend(backend)
756 return plot_backend.boxplot_frame_groupby(
757 grouped,
758 subplots=subplots,
759 column=column,
760 fontsize=fontsize,
761 rot=rot,
762 grid=grid,
763 ax=ax,
764 figsize=figsize,
765 layout=layout,
766 sharex=sharex,
767 sharey=sharey,
768 **kwargs,
769 )
770
771
772@set_module("pandas.plotting")
773class PlotAccessor(PandasObject):
774 """
775 Make plots of Series or DataFrame.
776
777 Uses the backend specified by the
778 option ``plotting.backend``. By default, matplotlib is used.
779
780 Parameters
781 ----------
782 data : Series or DataFrame
783 The object for which the method is called.
784
785 Attributes
786 ----------
787 x : label or position, default None
788 Only used if data is a DataFrame.
789 y : label, position or list of label, positions, default None
790 Allows plotting of one column versus another. Only used if data is a
791 DataFrame.
792 kind : str
793 The kind of plot to produce:
794
795 - 'line' : line plot (default)
796 - 'bar' : vertical bar plot
797 - 'barh' : horizontal bar plot
798 - 'hist' : histogram
799 - 'box' : boxplot
800 - 'kde' : Kernel Density Estimation plot
801 - 'density' : same as 'kde'
802 - 'area' : area plot
803 - 'pie' : pie plot
804 - 'scatter' : scatter plot (DataFrame only)
805 - 'hexbin' : hexbin plot (DataFrame only)
806 ax : matplotlib axes object, default None
807 An axes of the current figure.
808 subplots : bool or sequence of iterables, default False
809 Whether to group columns into subplots:
810
811 - ``False`` : No subplots will be used
812 - ``True`` : Make separate subplots for each column.
813 - sequence of iterables of column labels: Create a subplot for each
814 group of columns. For example `[('a', 'c'), ('b', 'd')]` will
815 create 2 subplots: one with columns 'a' and 'c', and one
816 with columns 'b' and 'd'. Remaining columns that aren't specified
817 will be plotted in additional subplots (one per column).
818
819 sharex : bool, default True if ax is None else False
820 In case ``subplots=True``, share x axis and set some x axis labels
821 to invisible; defaults to True if ax is None otherwise False if
822 an ax is passed in; Be aware, that passing in both an ax and
823 ``sharex=True`` will alter all x axis labels for all axis in a figure.
824 sharey : bool, default False
825 In case ``subplots=True``, share y axis and set some y axis labels to invisible.
826 layout : tuple, optional
827 (rows, columns) for the layout of subplots.
828 figsize : a tuple (width, height) in inches
829 Size of a figure object.
830 use_index : bool, default True
831 Use index as ticks for x axis.
832 title : str or list
833 Title to use for the plot. If a string is passed, print the string
834 at the top of the figure. If a list is passed and `subplots` is
835 True, print each item in the list above the corresponding subplot.
836 grid : bool, default None (matlab style default)
837 Axis grid lines.
838 legend : bool or {'reverse'}
839 Place legend on axis subplots.
840 style : list or dict
841 The matplotlib line style per column.
842 logx : bool or 'sym', default False
843 Use log scaling or symlog scaling on x axis.
844
845 logy : bool or 'sym' default False
846 Use log scaling or symlog scaling on y axis.
847
848 loglog : bool or 'sym', default False
849 Use log scaling or symlog scaling on both x and y axes.
850
851 xticks : sequence
852 Values to use for the xticks.
853 yticks : sequence
854 Values to use for the yticks.
855 xlim : 2-tuple/list
856 Set the x limits of the current axes.
857 ylim : 2-tuple/list
858 Set the y limits of the current axes.
859 xlabel : label, optional
860 Name to use for the xlabel on x-axis. Default uses index name as xlabel, or the
861 x-column name for planar plots.
862
863 .. versionchanged:: 2.0.0
864
865 Now applicable to histograms.
866
867 ylabel : label, optional
868 Name to use for the ylabel on y-axis. Default will show no ylabel, or the
869 y-column name for planar plots.
870
871 .. versionchanged:: 2.0.0
872
873 Now applicable to histograms.
874
875 rot : float, default None
876 Rotation for ticks (xticks for vertical, yticks for horizontal
877 plots).
878 fontsize : float, default None
879 Font size for xticks and yticks.
880 colormap : str or matplotlib colormap object, default None
881 Colormap to select colors from. If string, load colormap with that
882 name from matplotlib.
883 colorbar : bool, optional
884 If True, plot colorbar (only relevant for 'scatter' and 'hexbin'
885 plots).
886 position : float
887 Specify relative alignments for bar plot layout.
888 From 0 (left/bottom-end) to 1 (right/top-end). Default is 0.5
889 (center).
890 table : bool, Series or DataFrame, default False
891 If True, draw a table using the data in the DataFrame and the data
892 will be transposed to meet matplotlib's default layout.
893 If a Series or DataFrame is passed, use passed data to draw a
894 table.
895 yerr : DataFrame, Series, array-like, dict and str
896 See :ref:`Plotting with Error Bars <visualization.errorbars>` for
897 detail.
898 xerr : DataFrame, Series, array-like, dict and str
899 Equivalent to yerr.
900 stacked : bool, default False in line and bar plots, and True in area plot
901 If True, create stacked plot.
902 secondary_y : bool or sequence, default False
903 Whether to plot on the secondary y-axis if a list/tuple, which
904 columns to plot on secondary y-axis.
905 mark_right : bool, default True
906 When using a secondary_y axis, automatically mark the column
907 labels with "(right)" in the legend.
908 include_bool : bool, default is False
909 If True, boolean values can be plotted.
910 backend : str, default None
911 Backend to use instead of the backend specified in the option
912 ``plotting.backend``. For instance, 'matplotlib'. Alternatively, to
913 specify the ``plotting.backend`` for the whole session, set
914 ``pd.options.plotting.backend``.
915 **kwargs
916 Options to pass to matplotlib plotting method.
917
918 Returns
919 -------
920 :class:`matplotlib.axes.Axes` or numpy.ndarray of them
921 If the backend is not the default matplotlib one, the return value
922 will be the object returned by the backend.
923
924 See Also
925 --------
926 matplotlib.pyplot.plot : Plot y versus x as lines and/or markers.
927 DataFrame.hist : Make a histogram.
928 DataFrame.boxplot : Make a box plot.
929 DataFrame.plot.scatter : Make a scatter plot with varying marker
930 point size and color.
931 DataFrame.plot.hexbin : Make a hexagonal binning plot of
932 two variables.
933 DataFrame.plot.kde : Make Kernel Density Estimate plot using
934 Gaussian kernels.
935 DataFrame.plot.area : Make a stacked area plot.
936 DataFrame.plot.bar : Make a bar plot.
937 DataFrame.plot.barh : Make a horizontal bar plot.
938
939 Notes
940 -----
941 - See matplotlib documentation online for more on this subject
942 - If `kind` = 'bar' or 'barh', you can specify relative alignments
943 for bar plot layout by `position` keyword.
944 From 0 (left/bottom-end) to 1 (right/top-end). Default is 0.5
945 (center)
946
947 Examples
948 --------
949 For Series:
950
951 .. plot::
952 :context: close-figs
953
954 >>> ser = pd.Series([1, 2, 3, 3])
955 >>> plot = ser.plot(kind="hist", title="My plot")
956
957 For DataFrame:
958
959 .. plot::
960 :context: close-figs
961
962 >>> df = pd.DataFrame(
963 ... {
964 ... "length": [1.5, 0.5, 1.2, 0.9, 3],
965 ... "width": [0.7, 0.2, 0.15, 0.2, 1.1],
966 ... },
967 ... index=["pig", "rabbit", "duck", "chicken", "horse"],
968 ... )
969 >>> plot = df.plot(title="DataFrame Plot")
970
971 For SeriesGroupBy:
972
973 .. plot::
974 :context: close-figs
975
976 >>> lst = [-1, -2, -3, 1, 2, 3]
977 >>> ser = pd.Series([1, 2, 2, 4, 6, 6], index=lst)
978 >>> plot = ser.groupby(lambda x: x > 0).plot(title="SeriesGroupBy Plot")
979
980 For DataFrameGroupBy:
981
982 .. plot::
983 :context: close-figs
984
985 >>> df = pd.DataFrame({"col1": [1, 2, 3, 4], "col2": ["A", "B", "A", "B"]})
986 >>> plot = df.groupby("col2").plot(kind="bar", title="DataFrameGroupBy Plot")
987 """
988
989 _common_kinds = ("line", "bar", "barh", "kde", "density", "area", "hist", "box")
990 _series_kinds = ("pie",)
991 _dataframe_kinds = ("scatter", "hexbin")
992 _kind_aliases = {"density": "kde"}
993 _all_kinds = _common_kinds + _series_kinds + _dataframe_kinds
994
995 def __init__(self, data: Series | DataFrame) -> None:
996 self._parent = data
997
998 @staticmethod
999 def _get_call_args(backend_name: str, data: Series | DataFrame, args, kwargs):
1000 """
1001 This function makes calls to this accessor `__call__` method compatible
1002 with the previous `SeriesPlotMethods.__call__` and
1003 `DataFramePlotMethods.__call__`. Those had slightly different
1004 signatures, since `DataFramePlotMethods` accepted `x` and `y`
1005 parameters.
1006 """
1007 if isinstance(data, ABCSeries):
1008 arg_def = [
1009 ("kind", "line"),
1010 ("ax", None),
1011 ("figsize", None),
1012 ("use_index", True),
1013 ("title", None),
1014 ("grid", None),
1015 ("legend", False),
1016 ("style", None),
1017 ("logx", False),
1018 ("logy", False),
1019 ("loglog", False),
1020 ("xticks", None),
1021 ("yticks", None),
1022 ("xlim", None),
1023 ("ylim", None),
1024 ("rot", None),
1025 ("fontsize", None),
1026 ("colormap", None),
1027 ("table", False),
1028 ("yerr", None),
1029 ("xerr", None),
1030 ("label", None),
1031 ("secondary_y", False),
1032 ("xlabel", None),
1033 ("ylabel", None),
1034 ]
1035 elif isinstance(data, ABCDataFrame):
1036 arg_def = [
1037 ("x", None),
1038 ("y", None),
1039 ("kind", "line"),
1040 ("ax", None),
1041 ("subplots", False),
1042 ("sharex", None),
1043 ("sharey", False),
1044 ("layout", None),
1045 ("figsize", None),
1046 ("use_index", True),
1047 ("title", None),
1048 ("grid", None),
1049 ("legend", True),
1050 ("style", None),
1051 ("logx", False),
1052 ("logy", False),
1053 ("loglog", False),
1054 ("xticks", None),
1055 ("yticks", None),
1056 ("xlim", None),
1057 ("ylim", None),
1058 ("rot", None),
1059 ("fontsize", None),
1060 ("colormap", None),
1061 ("table", False),
1062 ("yerr", None),
1063 ("xerr", None),
1064 ("secondary_y", False),
1065 ("xlabel", None),
1066 ("ylabel", None),
1067 ]
1068 else:
1069 raise TypeError(
1070 f"Called plot accessor for type {type(data).__name__}, "
1071 "expected Series or DataFrame"
1072 )
1073
1074 if args and isinstance(data, ABCSeries):
1075 positional_args = str(args)[1:-1]
1076 keyword_args = ", ".join(
1077 [
1078 f"{name}={value!r}"
1079 for (name, _), value in zip(arg_def, args, strict=False)
1080 ]
1081 )
1082 msg = (
1083 "`Series.plot()` should not be called with positional "
1084 "arguments, only keyword arguments. The order of "
1085 "positional arguments will change in the future. "
1086 f"Use `Series.plot({keyword_args})` instead of "
1087 f"`Series.plot({positional_args})`."
1088 )
1089 raise TypeError(msg)
1090
1091 pos_args = {
1092 name: value for (name, _), value in zip(arg_def, args, strict=False)
1093 }
1094 if backend_name == "pandas.plotting._matplotlib":
1095 kwargs = dict(arg_def, **pos_args, **kwargs)
1096 else:
1097 kwargs = dict(pos_args, **kwargs)
1098
1099 x = kwargs.pop("x", None)
1100 y = kwargs.pop("y", None)
1101 kind = kwargs.pop("kind", "line")
1102 return x, y, kind, kwargs
1103
1104 def __call__(self, *args, **kwargs):
1105 plot_backend = _get_plot_backend(kwargs.pop("backend", None))
1106
1107 x, y, kind, kwargs = self._get_call_args(
1108 plot_backend.__name__, self._parent, args, kwargs
1109 )
1110
1111 kind = self._kind_aliases.get(kind, kind)
1112
1113 # when using another backend, get out of the way
1114 if plot_backend.__name__ != "pandas.plotting._matplotlib":
1115 return plot_backend.plot(self._parent, x=x, y=y, kind=kind, **kwargs)
1116
1117 if kind not in self._all_kinds:
1118 raise ValueError(
1119 f"{kind} is not a valid plot kind Valid plot kinds: {self._all_kinds}"
1120 )
1121
1122 data = self._parent
1123
1124 if isinstance(data, ABCSeries):
1125 kwargs["reuse_plot"] = True
1126
1127 if kind in self._dataframe_kinds:
1128 if isinstance(data, ABCDataFrame):
1129 return plot_backend.plot(data, x=x, y=y, kind=kind, **kwargs)
1130 else:
1131 raise ValueError(f"plot kind {kind} can only be used for data frames")
1132 elif kind in self._series_kinds:
1133 if isinstance(data, ABCDataFrame):
1134 if y is None and kwargs.get("subplots") is False:
1135 raise ValueError(
1136 f"{kind} requires either y column or 'subplots=True'"
1137 )
1138 if y is not None:
1139 if is_integer(y) and not holds_integer(data.columns):
1140 y = data.columns[y]
1141 # converted to series actually. copy to not modify
1142 data = data[y].copy(deep=False)
1143 data.index.name = y
1144 elif isinstance(data, ABCDataFrame):
1145 data_cols = data.columns
1146 if x is not None:
1147 if is_integer(x) and not holds_integer(data.columns):
1148 x = data_cols[x]
1149 elif not isinstance(data[x], ABCSeries):
1150 raise ValueError("x must be a label or position")
1151 data = data.set_index(x)
1152 if y is not None:
1153 # check if we have y as int or list of ints
1154 int_ylist = is_list_like(y) and all(is_integer(c) for c in y)
1155 int_y_arg = is_integer(y) or int_ylist
1156 if int_y_arg and not holds_integer(data.columns):
1157 y = data_cols[y]
1158
1159 label_kw = kwargs["label"] if "label" in kwargs else False
1160 for kw in ["xerr", "yerr"]:
1161 if kw in kwargs and (
1162 isinstance(kwargs[kw], str) or is_integer(kwargs[kw])
1163 ):
1164 try:
1165 kwargs[kw] = data[kwargs[kw]]
1166 except (IndexError, KeyError, TypeError):
1167 pass
1168
1169 data = data[y]
1170
1171 if isinstance(data, ABCSeries):
1172 label_name = label_kw or y
1173 data.name = label_name
1174 else:
1175 # error: Argument 1 to "len" has incompatible type "Any | bool";
1176 # expected "Sized" [arg-type]
1177 match = is_list_like(label_kw) and len(label_kw) == len(y) # type: ignore[arg-type]
1178 if label_kw and not match:
1179 raise ValueError(
1180 "label should be list-like and same length as y"
1181 )
1182 label_name = label_kw or data.columns
1183 data.columns = label_name
1184
1185 return plot_backend.plot(data, kind=kind, **kwargs)
1186
1187 __call__.__doc__ = __doc__
1188
1189 def line(
1190 self,
1191 x: Hashable | None = None,
1192 y: Hashable | None = None,
1193 color: str | Sequence[str] | dict | None = None,
1194 **kwargs,
1195 ) -> PlotAccessor:
1196 """
1197 Plot Series or DataFrame as lines.
1198
1199 This function is useful to plot lines using DataFrame's values
1200 as coordinates.
1201
1202 Parameters
1203 ----------
1204 x : label or position, optional
1205 Allows plotting of one column versus another. If not specified,
1206 the index of the DataFrame is used.
1207 y : label or position, optional
1208 Allows plotting of one column versus another. If not specified,
1209 all numerical columns are used.
1210 color : str, array-like, or dict, optional
1211 The color for each of the DataFrame's columns. Possible values are:
1212
1213 - A single color string referred to by name, RGB or RGBA code,
1214 for instance 'red' or '#a98d19'.
1215
1216 - A sequence of color strings referred to by name, RGB or RGBA
1217 code, which will be used for each column recursively. For
1218 instance ['green','yellow'] each column's line will be filled in
1219 green or yellow, alternatively. If there is only a single column to
1220 be plotted, then only the first color from the color list will be
1221 used.
1222
1223 - A dict of the form {column name : color}, so that each column will be
1224 colored accordingly. For example, if your columns are called `a` and
1225 `b`, then passing {'a': 'green', 'b': 'red'} will color lines for
1226 column `a` in green and lines for column `b` in red.
1227
1228 **kwargs
1229 Additional keyword arguments are documented in
1230 :meth:`DataFrame.plot`.
1231
1232 Returns
1233 -------
1234 matplotlib.axes.Axes or np.ndarray of them
1235 An ndarray is returned with one :class:`matplotlib.axes.Axes`
1236 per column when ``subplots=True``.
1237
1238 See Also
1239 --------
1240 matplotlib.pyplot.plot : Plot y versus x as lines and/or markers.
1241
1242 Examples
1243 --------
1244
1245 .. plot::
1246 :context: close-figs
1247
1248 >>> s = pd.Series([1, 3, 2])
1249 >>> s.plot.line() # doctest: +SKIP
1250
1251 .. plot::
1252 :context: close-figs
1253
1254 The following example shows the populations for some animals
1255 over the years.
1256
1257 >>> df = pd.DataFrame(
1258 ... {
1259 ... "pig": [20, 18, 489, 675, 1776],
1260 ... "horse": [4, 25, 281, 600, 1900],
1261 ... },
1262 ... index=[1990, 1997, 2003, 2009, 2014],
1263 ... )
1264 >>> lines = df.plot.line()
1265
1266 .. plot::
1267 :context: close-figs
1268
1269 An example with subplots, so an array of axes is returned.
1270
1271 >>> axes = df.plot.line(subplots=True)
1272 >>> type(axes)
1273 <class 'numpy.ndarray'>
1274
1275 .. plot::
1276 :context: close-figs
1277
1278 Let's repeat the same example, but specifying colors for
1279 each column (in this case, for each animal).
1280
1281 >>> axes = df.plot.line(
1282 ... subplots=True, color={"pig": "pink", "horse": "#742802"}
1283 ... )
1284
1285 .. plot::
1286 :context: close-figs
1287
1288 The following example shows the relationship between both
1289 populations.
1290
1291 >>> lines = df.plot.line(x="pig", y="horse")
1292 """
1293 if color is not None:
1294 kwargs["color"] = color
1295 return self(kind="line", x=x, y=y, **kwargs)
1296
1297 def bar(
1298 self,
1299 x: Hashable | None = None,
1300 y: Hashable | None = None,
1301 color: str | Sequence[str] | dict | None = None,
1302 **kwargs,
1303 ) -> PlotAccessor:
1304 """
1305 Vertical bar plot.
1306
1307 A bar plot is a plot that presents categorical data with
1308 rectangular bars with lengths proportional to the values that they
1309 represent. A bar plot shows comparisons among discrete categories. One
1310 axis of the plot shows the specific categories being compared, and the
1311 other axis represents a measured value.
1312
1313 Parameters
1314 ----------
1315 x : label or position, optional
1316 Allows plotting of one column versus another. If not specified,
1317 the index of the DataFrame is used.
1318 y : label or position, optional
1319 Allows plotting of one column versus another. If not specified,
1320 all numerical columns are used.
1321 color : str, array-like, or dict, optional
1322 The color for each of the DataFrame's columns. Possible values are:
1323
1324 - A single color string referred to by name, RGB or RGBA code,
1325 for instance 'red' or '#a98d19'.
1326
1327 - A sequence of color strings referred to by name, RGB or RGBA
1328 code, which will be used for each column recursively. For
1329 instance ['green','yellow'] each column's bar will be filled in
1330 green or yellow, alternatively. If there is only a single column to
1331 be plotted, then only the first color from the color list will be
1332 used.
1333
1334 - A dict of the form {column name : color}, so that each column will be
1335 colored accordingly. For example, if your columns are called `a` and
1336 `b`, then passing {'a': 'green', 'b': 'red'} will color bars for
1337 column `a` in green and bars for column `b` in red.
1338
1339 **kwargs
1340 Additional keyword arguments are documented in
1341 :meth:`DataFrame.plot`.
1342
1343 Returns
1344 -------
1345 matplotlib.axes.Axes or np.ndarray of them
1346 An ndarray is returned with one :class:`matplotlib.axes.Axes`
1347 per column when ``subplots=True``.
1348
1349 See Also
1350 --------
1351 DataFrame.plot.barh : Horizontal bar plot.
1352 DataFrame.plot : Make plots of a DataFrame.
1353 matplotlib.pyplot.bar : Make a bar plot with matplotlib.
1354
1355 Examples
1356 --------
1357 Basic plot.
1358
1359 .. plot::
1360 :context: close-figs
1361
1362 >>> df = pd.DataFrame({"lab": ["A", "B", "C"], "val": [10, 30, 20]})
1363 >>> ax = df.plot.bar(x="lab", y="val", rot=0)
1364
1365 Plot a whole dataframe to a bar plot. Each column is assigned a
1366 distinct color, and each row is nested in a group along the
1367 horizontal axis.
1368
1369 .. plot::
1370 :context: close-figs
1371
1372 >>> speed = [0.1, 17.5, 40, 48, 52, 69, 88]
1373 >>> lifespan = [2, 8, 70, 1.5, 25, 12, 28]
1374 >>> index = [
1375 ... "snail",
1376 ... "pig",
1377 ... "elephant",
1378 ... "rabbit",
1379 ... "giraffe",
1380 ... "coyote",
1381 ... "horse",
1382 ... ]
1383 >>> df = pd.DataFrame({"speed": speed, "lifespan": lifespan}, index=index)
1384 >>> ax = df.plot.bar(rot=0)
1385
1386 Plot stacked bar charts for the DataFrame
1387
1388 .. plot::
1389 :context: close-figs
1390
1391 >>> ax = df.plot.bar(stacked=True)
1392
1393 Instead of nesting, the figure can be split by column with
1394 ``subplots=True``. In this case, a :class:`numpy.ndarray` of
1395 :class:`matplotlib.axes.Axes` are returned.
1396
1397 .. plot::
1398 :context: close-figs
1399
1400 >>> axes = df.plot.bar(rot=0, subplots=True)
1401 >>> axes[1].legend(loc=2) # doctest: +SKIP
1402
1403 If you don't like the default colours, you can specify how you'd
1404 like each column to be colored.
1405
1406 .. plot::
1407 :context: close-figs
1408
1409 >>> axes = df.plot.bar(
1410 ... rot=0,
1411 ... subplots=True,
1412 ... color={"speed": "red", "lifespan": "green"},
1413 ... )
1414 >>> axes[1].legend(loc=2) # doctest: +SKIP
1415
1416 Plot a single column.
1417
1418 .. plot::
1419 :context: close-figs
1420
1421 >>> ax = df.plot.bar(y="speed", rot=0)
1422
1423 Plot only selected categories for the DataFrame.
1424
1425 .. plot::
1426 :context: close-figs
1427
1428 >>> ax = df.plot.bar(x="lifespan", rot=0)
1429 """
1430 if color is not None:
1431 kwargs["color"] = color
1432 return self(kind="bar", x=x, y=y, **kwargs)
1433
1434 def barh(
1435 self,
1436 x: Hashable | None = None,
1437 y: Hashable | None = None,
1438 color: str | Sequence[str] | dict | None = None,
1439 **kwargs,
1440 ) -> PlotAccessor:
1441 """
1442 Make a horizontal bar plot.
1443
1444 A horizontal bar plot is a plot that presents quantitative data with
1445 rectangular bars with lengths proportional to the values that they
1446 represent. A bar plot shows comparisons among discrete categories. One
1447 axis of the plot shows the specific categories being compared, and the
1448 other axis represents a measured value.
1449
1450 Parameters
1451 ----------
1452 x : label or position, optional
1453 Allows plotting of one column versus another. If not specified,
1454 the index of the DataFrame is used.
1455 y : label or position, optional
1456 Allows plotting of one column versus another. If not specified,
1457 all numerical columns are used.
1458 color : str, array-like, or dict, optional
1459 The color for each of the DataFrame's columns. Possible values are:
1460
1461 - A single color string referred to by name, RGB or RGBA code,
1462 for instance 'red' or '#a98d19'.
1463
1464 - A sequence of color strings referred to by name, RGB or RGBA
1465 code, which will be used for each column recursively. For
1466 instance ['green','yellow'] each column's bar will be filled in
1467 green or yellow, alternatively. If there is only a single column to
1468 be plotted, then only the first color from the color list will be
1469 used.
1470
1471 - A dict of the form {column name : color}, so that each column will be
1472 colored accordingly. For example, if your columns are called `a` and
1473 `b`, then passing {'a': 'green', 'b': 'red'} will color bars for
1474 column `a` in green and bars for column `b` in red.
1475
1476 **kwargs
1477 Additional keyword arguments are documented in
1478 :meth:`DataFrame.plot`.
1479
1480 Returns
1481 -------
1482 matplotlib.axes.Axes or np.ndarray of them
1483 An ndarray is returned with one :class:`matplotlib.axes.Axes`
1484 per column when ``subplots=True``.
1485
1486 See Also
1487 --------
1488 DataFrame.plot.bar : Vertical bar plot.
1489 DataFrame.plot : Make plots of DataFrame using matplotlib.
1490 matplotlib.axes.Axes.bar : Plot a vertical bar plot using matplotlib.
1491
1492 Examples
1493 --------
1494 Basic example
1495
1496 .. plot::
1497 :context: close-figs
1498
1499 >>> df = pd.DataFrame({"lab": ["A", "B", "C"], "val": [10, 30, 20]})
1500 >>> ax = df.plot.barh(x="lab", y="val")
1501
1502 Plot a whole DataFrame to a horizontal bar plot
1503
1504 .. plot::
1505 :context: close-figs
1506
1507 >>> speed = [0.1, 17.5, 40, 48, 52, 69, 88]
1508 >>> lifespan = [2, 8, 70, 1.5, 25, 12, 28]
1509 >>> index = [
1510 ... "snail",
1511 ... "pig",
1512 ... "elephant",
1513 ... "rabbit",
1514 ... "giraffe",
1515 ... "coyote",
1516 ... "horse",
1517 ... ]
1518 >>> df = pd.DataFrame({"speed": speed, "lifespan": lifespan}, index=index)
1519 >>> ax = df.plot.barh()
1520
1521 Plot stacked barh charts for the DataFrame
1522
1523 .. plot::
1524 :context: close-figs
1525
1526 >>> ax = df.plot.barh(stacked=True)
1527
1528 We can specify colors for each column
1529
1530 .. plot::
1531 :context: close-figs
1532
1533 >>> ax = df.plot.barh(color={"speed": "red", "lifespan": "green"})
1534
1535 Plot a column of the DataFrame to a horizontal bar plot
1536
1537 .. plot::
1538 :context: close-figs
1539
1540 >>> speed = [0.1, 17.5, 40, 48, 52, 69, 88]
1541 >>> lifespan = [2, 8, 70, 1.5, 25, 12, 28]
1542 >>> index = [
1543 ... "snail",
1544 ... "pig",
1545 ... "elephant",
1546 ... "rabbit",
1547 ... "giraffe",
1548 ... "coyote",
1549 ... "horse",
1550 ... ]
1551 >>> df = pd.DataFrame({"speed": speed, "lifespan": lifespan}, index=index)
1552 >>> ax = df.plot.barh(y="speed")
1553
1554 Plot DataFrame versus the desired column
1555
1556 .. plot::
1557 :context: close-figs
1558
1559 >>> speed = [0.1, 17.5, 40, 48, 52, 69, 88]
1560 >>> lifespan = [2, 8, 70, 1.5, 25, 12, 28]
1561 >>> index = [
1562 ... "snail",
1563 ... "pig",
1564 ... "elephant",
1565 ... "rabbit",
1566 ... "giraffe",
1567 ... "coyote",
1568 ... "horse",
1569 ... ]
1570 >>> df = pd.DataFrame({"speed": speed, "lifespan": lifespan}, index=index)
1571 >>> ax = df.plot.barh(x="lifespan")
1572 """
1573 if color is not None:
1574 kwargs["color"] = color
1575 return self(kind="barh", x=x, y=y, **kwargs)
1576
1577 def box(self, by: IndexLabel | None = None, **kwargs) -> PlotAccessor:
1578 r"""
1579 Make a box plot of the DataFrame columns.
1580
1581 A box plot is a method for graphically depicting groups of numerical
1582 data through their quartiles.
1583 The box extends from the Q1 to Q3 quartile values of the data,
1584 with a line at the median (Q2). The whiskers extend from the edges
1585 of box to show the range of the data. The position of the whiskers
1586 is set by default to 1.5*IQR (IQR = Q3 - Q1) from the edges of the
1587 box. Outlier points are those past the end of the whiskers.
1588
1589 For further details see Wikipedia's
1590 entry for `boxplot <https://en.wikipedia.org/wiki/Box_plot>`__.
1591
1592 A consideration when using this chart is that the box and the whiskers
1593 can overlap, which is very common when plotting small sets of data.
1594
1595 Parameters
1596 ----------
1597 by : str or sequence
1598 Column in the DataFrame to group by.
1599
1600 **kwargs
1601 Additional keywords are documented in
1602 :meth:`DataFrame.plot`.
1603
1604 Returns
1605 -------
1606 :class:`matplotlib.axes.Axes` or numpy.ndarray of them
1607 The matplotlib axes containing the box plot.
1608
1609 See Also
1610 --------
1611 DataFrame.boxplot: Another method to draw a box plot.
1612 Series.plot.box: Draw a box plot from a Series object.
1613 matplotlib.pyplot.boxplot: Draw a box plot in matplotlib.
1614
1615 Examples
1616 --------
1617 Draw a box plot from a DataFrame with four columns of randomly
1618 generated data.
1619
1620 .. plot::
1621 :context: close-figs
1622
1623 >>> data = np.random.randn(25, 4)
1624 >>> df = pd.DataFrame(data, columns=list("ABCD"))
1625 >>> ax = df.plot.box()
1626
1627 You can also generate groupings if you specify the `by` parameter (which
1628 can take a column name, or a list or tuple of column names):
1629
1630 .. plot::
1631 :context: close-figs
1632
1633 >>> age_list = [8, 10, 12, 14, 72, 74, 76, 78, 20, 25, 30, 35, 60, 85]
1634 >>> df = pd.DataFrame({"gender": list("MMMMMMMMFFFFFF"), "age": age_list})
1635 >>> ax = df.plot.box(column="age", by="gender", figsize=(10, 8))
1636 """
1637 return self(kind="box", by=by, **kwargs)
1638
1639 def hist(
1640 self, by: IndexLabel | None = None, bins: int = 10, **kwargs
1641 ) -> PlotAccessor:
1642 """
1643 Draw one histogram of the DataFrame's columns.
1644
1645 A histogram is a representation of the distribution of data.
1646 This function groups the values of all given Series in the DataFrame
1647 into bins and draws all bins in one :class:`matplotlib.axes.Axes`.
1648 This is useful when the DataFrame's Series are in a similar scale.
1649
1650 Parameters
1651 ----------
1652 by : str or sequence, optional
1653 Column in the DataFrame to group by.
1654 bins : int, default 10
1655 Number of histogram bins to be used.
1656 **kwargs
1657 Additional keyword arguments are documented in
1658 :meth:`DataFrame.plot`.
1659
1660 Returns
1661 -------
1662 :class:`matplotlib.axes.Axes`
1663 Return a histogram plot.
1664
1665 See Also
1666 --------
1667 DataFrame.hist : Draw histograms per DataFrame's Series.
1668 Series.hist : Draw a histogram with Series' data.
1669
1670 Examples
1671 --------
1672 When we roll a die 6000 times, we expect to get each value around 1000
1673 times. But when we roll two dice and sum the result, the distribution
1674 is going to be quite different. A histogram illustrates those
1675 distributions.
1676
1677 .. plot::
1678 :context: close-figs
1679
1680 >>> df = pd.DataFrame(np.random.randint(1, 7, 6000), columns=["one"])
1681 >>> df["two"] = df["one"] + np.random.randint(1, 7, 6000)
1682 >>> ax = df.plot.hist(bins=12, alpha=0.5)
1683
1684 A grouped histogram can be generated by providing the parameter `by` (which
1685 can be a column name, or a list of column names):
1686
1687 .. plot::
1688 :context: close-figs
1689
1690 >>> age_list = [8, 10, 12, 14, 72, 74, 76, 78, 20, 25, 30, 35, 60, 85]
1691 >>> df = pd.DataFrame({"gender": list("MMMMMMMMFFFFFF"), "age": age_list})
1692 >>> ax = df.plot.hist(column=["age"], by="gender", figsize=(10, 8))
1693 """
1694 return self(kind="hist", by=by, bins=bins, **kwargs)
1695
1696 def kde(
1697 self,
1698 bw_method: Literal["scott", "silverman"] | float | Callable | None = None,
1699 ind: np.ndarray | int | None = None,
1700 weights: np.ndarray | None = None,
1701 **kwargs,
1702 ) -> PlotAccessor:
1703 """
1704 Generate Kernel Density Estimate plot using Gaussian kernels.
1705
1706 In statistics, `kernel density estimation`_ (KDE) is a non-parametric
1707 way to estimate the probability density function (PDF) of a random
1708 variable. This function uses Gaussian kernels and includes automatic
1709 bandwidth determination.
1710
1711 .. _kernel density estimation:
1712 https://en.wikipedia.org/wiki/Kernel_density_estimation
1713
1714 Parameters
1715 ----------
1716 bw_method : str, scalar or callable, optional
1717 The method used to calculate the estimator bandwidth. This can be
1718 'scott', 'silverman', a scalar constant or a callable.
1719 If None (default), 'scott' is used.
1720 See :class:`scipy.stats.gaussian_kde` for more information.
1721 ind : NumPy array or int, optional
1722 Evaluation points for the estimated PDF. If None (default),
1723 1000 equally spaced points are used. If `ind` is a NumPy array, the
1724 KDE is evaluated at the points passed. If `ind` is an integer,
1725 `ind` number of equally spaced points are used.
1726 weights : NumPy array, optional
1727 Weights of datapoints. This must be the same shape as datapoints.
1728 If None (default), the samples are assumed to be equally weighted.
1729 **kwargs
1730 Additional keyword arguments are documented in
1731 :meth:`DataFrame.plot`.
1732
1733 Returns
1734 -------
1735 matplotlib.axes.Axes or numpy.ndarray of them
1736 The matplotlib axes containing the KDE plot.
1737
1738 See Also
1739 --------
1740 scipy.stats.gaussian_kde : Representation of a kernel-density
1741 estimate using Gaussian kernels. This is the function used
1742 internally to estimate the PDF.
1743
1744 Examples
1745 --------
1746 Given a Series of points randomly sampled from an unknown
1747 distribution, estimate its PDF using KDE with automatic
1748 bandwidth determination and plot the results, evaluating them at
1749 1000 equally spaced points (default):
1750
1751 .. plot::
1752 :context: close-figs
1753
1754 >>> s = pd.Series([1, 2, 2.5, 3, 3.5, 4, 5])
1755 >>> ax = s.plot.kde()
1756
1757 A scalar bandwidth can be specified. Using a small bandwidth value can
1758 lead to over-fitting, while using a large bandwidth value may result
1759 in under-fitting:
1760
1761 .. plot::
1762 :context: close-figs
1763
1764 >>> ax = s.plot.kde(bw_method=0.3)
1765
1766 .. plot::
1767 :context: close-figs
1768
1769 >>> ax = s.plot.kde(bw_method=3)
1770
1771 Finally, the `ind` parameter determines the evaluation points for the
1772 plot of the estimated PDF:
1773
1774 .. plot::
1775 :context: close-figs
1776
1777 >>> ax = s.plot.kde(ind=[1, 2, 3, 4, 5])
1778
1779 For DataFrame, it works in the same way:
1780
1781 .. plot::
1782 :context: close-figs
1783
1784 >>> df = pd.DataFrame(
1785 ... {
1786 ... "x": [1, 2, 2.5, 3, 3.5, 4, 5],
1787 ... "y": [4, 4, 4.5, 5, 5.5, 6, 6],
1788 ... }
1789 ... )
1790 >>> ax = df.plot.kde()
1791
1792 A scalar bandwidth can be specified. Using a small bandwidth value can
1793 lead to over-fitting, while using a large bandwidth value may result
1794 in under-fitting:
1795
1796 .. plot::
1797 :context: close-figs
1798
1799 >>> ax = df.plot.kde(bw_method=0.3)
1800
1801 .. plot::
1802 :context: close-figs
1803
1804 >>> ax = df.plot.kde(bw_method=3)
1805
1806 Finally, the `ind` parameter determines the evaluation points for the
1807 plot of the estimated PDF:
1808
1809 .. plot::
1810 :context: close-figs
1811
1812 >>> ax = df.plot.kde(ind=[1, 2, 3, 4, 5, 6])
1813 """
1814 return self(kind="kde", bw_method=bw_method, ind=ind, weights=weights, **kwargs)
1815
1816 density = kde
1817
1818 def area(
1819 self,
1820 x: Hashable | None = None,
1821 y: Hashable | None = None,
1822 stacked: bool = True,
1823 **kwargs,
1824 ) -> PlotAccessor:
1825 """
1826 Draw a stacked area plot.
1827
1828 An area plot displays quantitative data visually.
1829 This function wraps the matplotlib area function.
1830
1831 Parameters
1832 ----------
1833 x : label or position, optional
1834 Coordinates for the X axis. By default uses the index.
1835 y : label or position, optional
1836 Column to plot. By default uses all columns.
1837 stacked : bool, default True
1838 Area plots are stacked by default. Set to False to create a
1839 unstacked plot.
1840 **kwargs
1841 Additional keyword arguments are documented in
1842 :meth:`DataFrame.plot`.
1843
1844 Returns
1845 -------
1846 matplotlib.axes.Axes or numpy.ndarray
1847 Area plot, or array of area plots if subplots is True.
1848
1849 See Also
1850 --------
1851 DataFrame.plot : Make plots of DataFrame using matplotlib.
1852
1853 Examples
1854 --------
1855 Draw an area plot based on basic business metrics:
1856
1857 .. plot::
1858 :context: close-figs
1859
1860 >>> df = pd.DataFrame(
1861 ... {
1862 ... "sales": [3, 2, 3, 9, 10, 6],
1863 ... "signups": [5, 5, 6, 12, 14, 13],
1864 ... "visits": [20, 42, 28, 62, 81, 50],
1865 ... },
1866 ... index=pd.date_range(
1867 ... start="2018/01/01", end="2018/07/01", freq="ME"
1868 ... ),
1869 ... )
1870 >>> ax = df.plot.area()
1871
1872 Area plots are stacked by default. To produce an unstacked plot,
1873 pass ``stacked=False``:
1874
1875 .. plot::
1876 :context: close-figs
1877
1878 >>> ax = df.plot.area(stacked=False)
1879
1880 Draw an area plot for a single column:
1881
1882 .. plot::
1883 :context: close-figs
1884
1885 >>> ax = df.plot.area(y="sales")
1886
1887 Draw with a different `x`:
1888
1889 .. plot::
1890 :context: close-figs
1891
1892 >>> df = pd.DataFrame(
1893 ... {
1894 ... "sales": [3, 2, 3],
1895 ... "visits": [20, 42, 28],
1896 ... "day": [1, 2, 3],
1897 ... }
1898 ... )
1899 >>> ax = df.plot.area(x="day")
1900 """
1901 return self(kind="area", x=x, y=y, stacked=stacked, **kwargs)
1902
1903 def pie(self, y: IndexLabel | None = None, **kwargs) -> PlotAccessor:
1904 """
1905 Generate a pie plot.
1906
1907 A pie plot is a proportional representation of the numerical data in a
1908 column. This function wraps :meth:`matplotlib.pyplot.pie` for the
1909 specified column. If no column reference is passed and
1910 ``subplots=True`` a pie plot is drawn for each numerical column
1911 independently.
1912
1913 Parameters
1914 ----------
1915 y : int or label, optional
1916 Label or position of the column to plot.
1917 If not provided, ``subplots=True`` argument must be passed.
1918 **kwargs
1919 Keyword arguments to pass on to :meth:`DataFrame.plot`.
1920
1921 Returns
1922 -------
1923 matplotlib.axes.Axes or np.ndarray of them
1924 A NumPy array is returned when `subplots` is True.
1925
1926 See Also
1927 --------
1928 Series.plot.pie : Generate a pie plot for a Series.
1929 DataFrame.plot : Make plots of a DataFrame.
1930
1931 Examples
1932 --------
1933 In the example below we have a DataFrame with the information about
1934 planet's mass and radius. We pass the 'mass' column to the
1935 pie function to get a pie plot.
1936
1937 .. plot::
1938 :context: close-figs
1939
1940 >>> df = pd.DataFrame(
1941 ... {"mass": [0.330, 4.87, 5.97], "radius": [2439.7, 6051.8, 6378.1]},
1942 ... index=["Mercury", "Venus", "Earth"],
1943 ... )
1944 >>> plot = df.plot.pie(y="mass", figsize=(5, 5))
1945
1946 .. plot::
1947 :context: close-figs
1948
1949 >>> plot = df.plot.pie(subplots=True, figsize=(11, 6))
1950 """
1951 if y is not None:
1952 kwargs["y"] = y
1953 if (
1954 isinstance(self._parent, ABCDataFrame)
1955 and kwargs.get("y", None) is None
1956 and not kwargs.get("subplots", False)
1957 ):
1958 raise ValueError("pie requires either y column or 'subplots=True'")
1959 return self(kind="pie", **kwargs)
1960
1961 def scatter(
1962 self,
1963 x: Hashable,
1964 y: Hashable,
1965 s: Hashable | Sequence[Hashable] | None = None,
1966 c: Hashable | Sequence[Hashable] | None = None,
1967 **kwargs,
1968 ) -> PlotAccessor:
1969 """
1970 Create a scatter plot with varying marker point size and color.
1971
1972 The coordinates of each point are defined by two dataframe columns and
1973 filled circles are used to represent each point. This kind of plot is
1974 useful to see complex correlations between two variables. Points could
1975 be for instance natural 2D coordinates like longitude and latitude in
1976 a map or, in general, any pair of metrics that can be plotted against
1977 each other.
1978
1979 Parameters
1980 ----------
1981 x : int or str
1982 The column name or column position to be used as horizontal
1983 coordinates for each point.
1984 y : int or str
1985 The column name or column position to be used as vertical
1986 coordinates for each point.
1987 s : str, scalar or array-like, optional
1988 The size of each point. Possible values are:
1989
1990 - A string with the name of the column to be used for marker's size.
1991
1992 - A single scalar so all points have the same size.
1993
1994 - A sequence of scalars, which will be used for each point's size
1995 recursively. For instance, when passing [2,14] all points size
1996 will be either 2 or 14, alternatively.
1997
1998 c : str, int or array-like, optional
1999 The color of each point. Possible values are:
2000
2001 - A single color string referred to by name, RGB or RGBA code,
2002 for instance 'red' or '#a98d19'.
2003
2004 - A sequence of color strings referred to by name, RGB or RGBA
2005 code, which will be used for each point's color recursively. For
2006 instance ['green','yellow'] all points will be filled in green or
2007 yellow, alternatively.
2008
2009 - A column name or position whose values will be used to color the
2010 marker points according to a colormap.
2011
2012 **kwargs
2013 Keyword arguments to pass on to :meth:`DataFrame.plot`.
2014
2015 Returns
2016 -------
2017 :class:`matplotlib.axes.Axes` or numpy.ndarray of them
2018 The matplotlib axes containing the scatter plot.
2019
2020 See Also
2021 --------
2022 matplotlib.pyplot.scatter : Scatter plot using multiple input data
2023 formats.
2024
2025 Examples
2026 --------
2027 Let's see how to draw a scatter plot using coordinates from the values
2028 in a DataFrame's columns.
2029
2030 .. plot::
2031 :context: close-figs
2032
2033 >>> df = pd.DataFrame(
2034 ... [
2035 ... [5.1, 3.5, 0],
2036 ... [4.9, 3.0, 0],
2037 ... [7.0, 3.2, 1],
2038 ... [6.4, 3.2, 1],
2039 ... [5.9, 3.0, 2],
2040 ... ],
2041 ... columns=["length", "width", "species"],
2042 ... )
2043 >>> ax1 = df.plot.scatter(x="length", y="width", c="DarkBlue")
2044
2045 And now with the color determined by a column as well.
2046
2047 .. plot::
2048 :context: close-figs
2049
2050 >>> ax2 = df.plot.scatter(
2051 ... x="length", y="width", c="species", colormap="viridis"
2052 ... )
2053 """
2054 return self(kind="scatter", x=x, y=y, s=s, c=c, **kwargs)
2055
2056 def hexbin(
2057 self,
2058 x: Hashable,
2059 y: Hashable,
2060 C: Hashable | None = None,
2061 reduce_C_function: Callable | None = None,
2062 gridsize: int | tuple[int, int] | None = None,
2063 **kwargs,
2064 ) -> PlotAccessor:
2065 """
2066 Generate a hexagonal binning plot.
2067
2068 Generate a hexagonal binning plot of `x` versus `y`. If `C` is `None`
2069 (the default), this is a histogram of the number of occurrences
2070 of the observations at ``(x[i], y[i])``.
2071
2072 If `C` is specified, specifies values at given coordinates
2073 ``(x[i], y[i])``. These values are accumulated for each hexagonal
2074 bin and then reduced according to `reduce_C_function`,
2075 having as default the NumPy's mean function (:meth:`numpy.mean`).
2076 (If `C` is specified, it must also be a 1-D sequence
2077 of the same length as `x` and `y`, or a column label.)
2078
2079 Parameters
2080 ----------
2081 x : int or str
2082 The column label or position for x points.
2083 y : int or str
2084 The column label or position for y points.
2085 C : int or str, optional
2086 The column label or position for the value of `(x, y)` point.
2087 reduce_C_function : callable, default `np.mean`
2088 Function of one argument that reduces all the values in a bin to
2089 a single number (e.g. `np.mean`, `np.max`, `np.sum`, `np.std`).
2090 gridsize : int or tuple of (int, int), default 100
2091 The number of hexagons in the x-direction.
2092 The corresponding number of hexagons in the y-direction is
2093 chosen in a way that the hexagons are approximately regular.
2094 Alternatively, gridsize can be a tuple with two elements
2095 specifying the number of hexagons in the x-direction and the
2096 y-direction.
2097 **kwargs
2098 Additional keyword arguments are documented in
2099 :meth:`DataFrame.plot`.
2100
2101 Returns
2102 -------
2103 matplotlib.Axes
2104 The matplotlib ``Axes`` on which the hexbin is plotted.
2105
2106 See Also
2107 --------
2108 DataFrame.plot : Make plots of a DataFrame.
2109 matplotlib.pyplot.hexbin : Hexagonal binning plot using matplotlib,
2110 the matplotlib function that is used under the hood.
2111
2112 Examples
2113 --------
2114 The following examples are generated with random data from
2115 a normal distribution.
2116
2117 .. plot::
2118 :context: close-figs
2119
2120 >>> n = 10000
2121 >>> df = pd.DataFrame({"x": np.random.randn(n), "y": np.random.randn(n)})
2122 >>> ax = df.plot.hexbin(x="x", y="y", gridsize=20)
2123
2124 The next example uses `C` and `np.sum` as `reduce_C_function`.
2125 Note that `'observations'` values ranges from 1 to 5 but the result
2126 plot shows values up to more than 25. This is because of the
2127 `reduce_C_function`.
2128
2129 .. plot::
2130 :context: close-figs
2131
2132 >>> n = 500
2133 >>> df = pd.DataFrame(
2134 ... {
2135 ... "coord_x": np.random.uniform(-3, 3, size=n),
2136 ... "coord_y": np.random.uniform(30, 50, size=n),
2137 ... "observations": np.random.randint(1, 5, size=n),
2138 ... }
2139 ... )
2140 >>> ax = df.plot.hexbin(
2141 ... x="coord_x",
2142 ... y="coord_y",
2143 ... C="observations",
2144 ... reduce_C_function=np.sum,
2145 ... gridsize=10,
2146 ... cmap="viridis",
2147 ... )
2148 """
2149 if reduce_C_function is not None:
2150 kwargs["reduce_C_function"] = reduce_C_function
2151 if gridsize is not None:
2152 kwargs["gridsize"] = gridsize
2153
2154 return self(kind="hexbin", x=x, y=y, C=C, **kwargs)
2155
2156
2157_backends: dict[str, types.ModuleType] = {}
2158
2159
2160def _load_backend(backend: str) -> types.ModuleType:
2161 """
2162 Load a pandas plotting backend.
2163
2164 Parameters
2165 ----------
2166 backend : str
2167 The identifier for the backend. Either an entrypoint item registered
2168 with importlib.metadata, "matplotlib", or a module name.
2169
2170 Returns
2171 -------
2172 types.ModuleType
2173 The imported backend.
2174 """
2175 from importlib.metadata import entry_points
2176
2177 if backend == "matplotlib":
2178 # Because matplotlib is an optional dependency and first-party backend,
2179 # we need to attempt an import here to raise an ImportError if needed.
2180 try:
2181 module = importlib.import_module("pandas.plotting._matplotlib")
2182 except ImportError:
2183 raise ImportError(
2184 "matplotlib is required for plotting when the "
2185 'default backend "matplotlib" is selected.'
2186 ) from None
2187 return module
2188
2189 found_backend = False
2190
2191 eps = entry_points()
2192 key = "pandas_plotting_backends"
2193 # entry_points lost dict API ~ PY 3.10
2194 # https://github.com/python/importlib_metadata/issues/298
2195 if hasattr(eps, "select"):
2196 entry = eps.select(group=key)
2197 else:
2198 # Argument 2 to "get" of "dict" has incompatible type "Tuple[]";
2199 # expected "EntryPoints" [arg-type]
2200 entry = eps.get(key, ()) # type: ignore[arg-type]
2201 for entry_point in entry:
2202 found_backend = entry_point.name == backend
2203 if found_backend:
2204 module = entry_point.load()
2205 break
2206
2207 if not found_backend:
2208 # Fall back to unregistered, module name approach.
2209 try:
2210 module = importlib.import_module(backend)
2211 found_backend = True
2212 except ImportError:
2213 # We re-raise later on.
2214 pass
2215
2216 if found_backend:
2217 if hasattr(module, "plot"):
2218 # Validate that the interface is implemented when the option is set,
2219 # rather than at plot time.
2220 return module
2221
2222 raise ValueError(
2223 f"Could not find plotting backend '{backend}'. Ensure that you've "
2224 f"installed the package providing the '{backend}' entrypoint, or that "
2225 "the package has a top-level `.plot` method."
2226 )
2227
2228
2229def _get_plot_backend(backend: str | None = None):
2230 """
2231 Return the plotting backend to use (e.g. `pandas.plotting._matplotlib`).
2232
2233 The plotting system of pandas uses matplotlib by default, but the idea here
2234 is that it can also work with other third-party backends. This function
2235 returns the module which provides a top-level `.plot` method that will
2236 actually do the plotting. The backend is specified from a string, which
2237 either comes from the keyword argument `backend`, or, if not specified, from
2238 the option `pandas.options.plotting.backend`. All the rest of the code in
2239 this file uses the backend specified there for the plotting.
2240
2241 The backend is imported lazily, as matplotlib is a soft dependency, and
2242 pandas can be used without it being installed.
2243
2244 Notes
2245 -----
2246 Modifies `_backends` with imported backend as a side effect.
2247 """
2248 backend_str: str = backend or get_option("plotting.backend")
2249
2250 if backend_str in _backends:
2251 return _backends[backend_str]
2252
2253 module = _load_backend(backend_str)
2254 _backends[backend_str] = module
2255 return module