Skip to content

Commit b07aba2

Browse files
committed
start plotting backend
1 parent d3c9d6e commit b07aba2

File tree

4 files changed

+144
-9
lines changed

4 files changed

+144
-9
lines changed

pandas/core/config_init.py

+25
Original file line numberDiff line numberDiff line change
@@ -505,3 +505,28 @@ def register_converter_cb(key):
505505
with cf.config_prefix("plotting.matplotlib"):
506506
cf.register_option("register_converters", True, register_converter_doc,
507507
validator=bool, cb=register_converter_cb)
508+
509+
510+
plotting_backend_doc = """
511+
: str
512+
The plotting backend to use.
513+
"""
514+
515+
516+
def plotting_backend_cb(key):
517+
from pandas import Series, DataFrame
518+
from pandas.plotting._base import _backends
519+
from pandas.core.accessor import CachedAccessor
520+
521+
backend_name = cf.get_option(key)
522+
print('registering', backend_name)
523+
backend = _backends[backend_name]
524+
525+
Series.plot = CachedAccessor("plot", backend.series)
526+
DataFrame.plot = CachedAccessor("plot", backend.frame)
527+
528+
529+
with cf.config_prefix("plotting"):
530+
cf.register_option("backend", defval="matplotlib",
531+
doc=plotting_backend_doc,
532+
cb=plotting_backend_cb)

pandas/plotting/_base.py

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
from collections import namedtuple
2+
3+
PlottingBackend = namedtuple('PlottingBackend', 'series frame')
4+
5+
_backends = {}
6+
7+
8+
def register_backend(name, series, frame):
9+
_backends[name] = PlottingBackend(series, frame)
10+
11+
12+
class BasePlotMethods:
13+
def __init__(self, data):
14+
self._parent = data
15+
16+
def __call__(self, *args, **kwargs):
17+
raise NotImplementedError
18+
19+
def area(self, *args, **kwargs):
20+
pass
21+
22+
def bar(self, *args, **kwargs):
23+
pass
24+
25+
def barh(self, *args, **kwargs):
26+
pass
27+
28+
def box(self, *args, **kwargs):
29+
pass
30+
31+
def density(self, *args, **kwargs):
32+
pass
33+
34+
def hist(self, *args, **kwargs):
35+
pass
36+
37+
def kde(self, *args, **kwargs):
38+
pass
39+
40+
def line(self, *args, **kwargs):
41+
pass
42+
43+
def pie(self, *args, **kwargs):
44+
pass
45+
46+
47+
class SeriesPlotMethods(BasePlotMethods):
48+
def __call__(self, kind='line', ax=None,
49+
figsize=None, use_index=True, title=None, grid=None,
50+
legend=False, style=None, logx=False, logy=False,
51+
loglog=False, xticks=None, yticks=None,
52+
xlim=None, ylim=None,
53+
rot=None, fontsize=None, colormap=None, table=False,
54+
yerr=None, xerr=None,
55+
label=None, secondary_y=False, **kwds):
56+
raise NotImplementedError
57+
58+
59+
class FramePlotMethods(BasePlotMethods):
60+
61+
def __call__(self, x=None, y=None, kind='line', ax=None,
62+
subplots=False, sharex=None, sharey=False, layout=None,
63+
figsize=None, use_index=True, title=None, grid=None,
64+
legend=True, style=None, logx=False, logy=False, loglog=False,
65+
xticks=None, yticks=None, xlim=None, ylim=None,
66+
rot=None, fontsize=None, colormap=None, table=False,
67+
yerr=None, xerr=None,
68+
secondary_y=False, sort_columns=False, **kwds):
69+
pass
70+
71+
def hexbin(self, x, y, **kwargs):
72+
pass
73+
74+
def scatter(self, x, y, **kwargs):
75+
pass

pandas/plotting/_core.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
_flatten, _get_all_lines, _get_xlim, _handle_shared_axes, _set_ticks_props,
3333
_subplots, format_date_labels, table)
3434

35+
from ._base import FramePlotMethods, SeriesPlotMethods, register_backend
36+
3537
try:
3638
from pandas.plotting import _converter
3739
except ImportError:
@@ -2697,16 +2699,11 @@ def _grouped_plot_by_column(plotf, data, columns=None, by=None,
26972699
return result
26982700

26992701

2700-
class BasePlotMethods(PandasObject):
2701-
2702-
def __init__(self, data):
2703-
self._parent = data # can be Series or DataFrame
2704-
2705-
def __call__(self, *args, **kwargs):
2706-
raise NotImplementedError
2702+
class BaseMPLMethods(PandasObject):
2703+
pass
27072704

27082705

2709-
class SeriesPlotMethods(BasePlotMethods):
2706+
class MPLSeriesMethods(BaseMPLMethods, SeriesPlotMethods):
27102707
"""
27112708
Series plotting accessor and method.
27122709
@@ -2906,7 +2903,7 @@ def pie(self, **kwds):
29062903
return self(kind='pie', **kwds)
29072904

29082905

2909-
class FramePlotMethods(BasePlotMethods):
2906+
class FramePlotMethods(BaseMPLMethods, FramePlotMethods):
29102907
"""DataFrame plotting accessor and method
29112908
29122909
Examples
@@ -3600,3 +3597,6 @@ def hexbin(self, x, y, C=None, reduce_C_function=None, gridsize=None,
36003597
if gridsize is not None:
36013598
kwds['gridsize'] = gridsize
36023599
return self(kind='hexbin', x=x, y=y, C=C, **kwds)
3600+
3601+
3602+
register_backend('matplotlib', SeriesPlotMethods, FramePlotMethods)
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import pandas as pd
2+
3+
from pandas.plotting._base import _backends, register_backend
4+
from pandas.plotting._core import FramePlotMethods, SeriesPlotMethods
5+
6+
7+
def test_register_backend():
8+
# define
9+
count = 0
10+
11+
class MockedSeries(SeriesPlotMethods):
12+
def line(self, *args, **kwargs):
13+
nonlocal count
14+
count += 1
15+
super().line(*args, **kwargs)
16+
17+
class MockedFrame(FramePlotMethods):
18+
def line(self, *args, **kwargs):
19+
nonlocal count
20+
count += 1
21+
super().line(*args, **kwargs)
22+
23+
# register
24+
register_backend('mocked', MockedSeries, MockedFrame)
25+
assert 'mocked' in _backends
26+
27+
# select
28+
pd.set_option("plotting.backend", "mocked")
29+
30+
# use
31+
df = pd.DataFrame({"A": [1, 2], "B": [1, 2]})
32+
df.plot.line()
33+
assert count == 1
34+
df['A'].plot.line()
35+
assert count == 2

0 commit comments

Comments
 (0)