Skip to content

Commit 903a09c

Browse files
datapythonistajreback
authored andcommitted
PLT: Cleaner plotting backend API, and unify Series and DataFrame accessors (#27009)
1 parent 4e185fc commit 903a09c

File tree

10 files changed

+634
-766
lines changed

10 files changed

+634
-766
lines changed

doc/source/development/extending.rst

+27
Original file line numberDiff line numberDiff line change
@@ -416,3 +416,30 @@ Below is an example to define two original properties, "internal_cache" as a tem
416416
# properties defined in _metadata are retained
417417
>>> df[['A', 'B']].added_property
418418
property
419+
420+
.. _extending.plotting-backends:
421+
422+
Plotting backends
423+
-----------------
424+
425+
Starting in 0.25 pandas can be extended with third-party plotting backends. The
426+
main idea is letting users select a plotting backend different than the provided
427+
one based on Matplotlib. For example:
428+
429+
.. code-block:: python
430+
431+
>>> pd.set_option('plotting.backend', 'backend.module')
432+
>>> pd.Series([1, 2, 3]).plot()
433+
434+
This would be more or less equivalent to:
435+
436+
.. code-block:: python
437+
438+
>>> import backend.module
439+
>>> backend.module.plot(pd.Series([1, 2, 3]))
440+
441+
The backend module can then use other visualization tools (Bokeh, Altair,...)
442+
to generate the plots.
443+
444+
More information on how to implement a third-party plotting backend can be found at
445+
https://github.com/pandas-dev/pandas/blob/master/pandas/plotting/__init__.py#L1.

pandas/core/frame.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -7946,7 +7946,7 @@ def isin(self, values):
79467946

79477947
# ----------------------------------------------------------------------
79487948
# Add plotting methods to DataFrame
7949-
plot = CachedAccessor("plot", pandas.plotting.FramePlotMethods)
7949+
plot = CachedAccessor("plot", pandas.plotting.PlotAccessor)
79507950
hist = pandas.plotting.hist_frame
79517951
boxplot = pandas.plotting.boxplot_frame
79527952
sparse = CachedAccessor("sparse", SparseFrameAccessor)

pandas/core/series.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4537,7 +4537,7 @@ def to_period(self, freq=None, copy=True):
45374537
str = CachedAccessor("str", StringMethods)
45384538
dt = CachedAccessor("dt", CombinedDatetimelikeProperties)
45394539
cat = CachedAccessor("cat", CategoricalAccessor)
4540-
plot = CachedAccessor("plot", pandas.plotting.SeriesPlotMethods)
4540+
plot = CachedAccessor("plot", pandas.plotting.PlotAccessor)
45414541
sparse = CachedAccessor("sparse", SparseAccessor)
45424542

45434543
# ----------------------------------------------------------------------

pandas/plotting/__init__.py

+63-8
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,73 @@
11
"""
2-
Plotting public API
2+
Plotting public API.
3+
4+
Authors of third-party plotting backends should implement a module with a
5+
public ``plot(data, kind, **kwargs)``. The parameter `data` will contain
6+
the data structure and can be a `Series` or a `DataFrame`. For example,
7+
for ``df.plot()`` the parameter `data` will contain the DataFrame `df`.
8+
In some cases, the data structure is transformed before being sent to
9+
the backend (see PlotAccessor.__call__ in pandas/plotting/_core.py for
10+
the exact transformations).
11+
12+
The parameter `kind` will be one of:
13+
14+
- line
15+
- bar
16+
- barh
17+
- box
18+
- hist
19+
- kde
20+
- area
21+
- pie
22+
- scatter
23+
- hexbin
24+
25+
See the pandas API reference for documentation on each kind of plot.
26+
27+
Any other keyword argument is currently assumed to be backend specific,
28+
but some parameters may be unified and added to the signature in the
29+
future (e.g. `title` which should be useful for any backend).
30+
31+
Currently, all the Matplotlib functions in pandas are accessed through
32+
the selected backend. For example, `pandas.plotting.boxplot` (equivalent
33+
to `DataFrame.boxplot`) is also accessed in the selected backend. This
34+
is expected to change, and the exact API is under discussion. But with
35+
the current version, backends are expected to implement the next functions:
36+
37+
- plot (describe above, used for `Series.plot` and `DataFrame.plot`)
38+
- hist_series and hist_frame (for `Series.hist` and `DataFrame.hist`)
39+
- boxplot (`pandas.plotting.boxplot(df)` equivalent to `DataFrame.boxplot`)
40+
- boxplot_frame and boxplot_frame_groupby
41+
- tsplot (deprecated)
42+
- register and deregister (register converters for the tick formats)
43+
- Plots not called as `Series` and `DataFrame` methods:
44+
- table
45+
- andrews_curves
46+
- autocorrelation_plot
47+
- bootstrap_plot
48+
- lag_plot
49+
- parallel_coordinates
50+
- radviz
51+
- scatter_matrix
52+
53+
Use the code in pandas/plotting/_matplotib.py and
54+
https://github.com/pyviz/hvplot as a reference on how to write a backend.
55+
56+
For the discussion about the API see
57+
https://github.com/pandas-dev/pandas/issues/26747.
358
"""
459
from pandas.plotting._core import (
5-
FramePlotMethods, SeriesPlotMethods, boxplot, boxplot_frame,
6-
boxplot_frame_groupby, hist_frame, hist_series)
60+
PlotAccessor, boxplot, boxplot_frame, boxplot_frame_groupby, hist_frame,
61+
hist_series)
762
from pandas.plotting._misc import (
863
andrews_curves, autocorrelation_plot, bootstrap_plot,
964
deregister as deregister_matplotlib_converters, lag_plot,
1065
parallel_coordinates, plot_params, radviz,
1166
register as register_matplotlib_converters, scatter_matrix, table)
1267

13-
__all__ = ['boxplot', 'boxplot_frame', 'boxplot_frame_groupby', 'hist_frame',
14-
'hist_series', 'FramePlotMethods', 'SeriesPlotMethods',
15-
'scatter_matrix', 'radviz', 'andrews_curves', 'bootstrap_plot',
16-
'parallel_coordinates', 'lag_plot', 'autocorrelation_plot',
17-
'table', 'plot_params', 'register_matplotlib_converters',
68+
__all__ = ['PlotAccessor', 'boxplot', 'boxplot_frame', 'boxplot_frame_groupby',
69+
'hist_frame', 'hist_series', 'scatter_matrix', 'radviz',
70+
'andrews_curves', 'bootstrap_plot', 'parallel_coordinates',
71+
'lag_plot', 'autocorrelation_plot', 'table', 'plot_params',
72+
'register_matplotlib_converters',
1873
'deregister_matplotlib_converters']

0 commit comments

Comments
 (0)