Skip to content

Add bokeh placeholder #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions pandas/core/config_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,3 +480,19 @@ def use_inf_as_na_cb(key):
cf.register_option(
'engine', 'auto', parquet_engine_doc,
validator=is_one_of_factory(['auto', 'pyarrow', 'fastparquet']))


# --------
# Plotting
# --------

plotting_engine_doc = """
: str
The name of a plotting engine.
"""


with cf.config_prefix("plotting"):
cf.register_option(
"engine", "auto", plotting_engine_doc, validator=str
)
5 changes: 3 additions & 2 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
import pandas.io.formats.console as console
from pandas.io.formats.printing import pprint_thing
import pandas.plotting._core as gfx
import pandas.plotting.base as gfx_base

from pandas._libs import lib, algos as libalgos

Expand Down Expand Up @@ -6128,8 +6129,8 @@ def isin(self, values):

# ----------------------------------------------------------------------
# Add plotting methods to DataFrame
plot = accessor.AccessorProperty(gfx.FramePlotMethods,
gfx.FramePlotMethods)
plot = accessor.AccessorProperty(gfx_base.Dispatcher,
gfx_base.Dispatcher)
hist = gfx.hist_frame
boxplot = gfx.boxplot_frame

Expand Down
5 changes: 3 additions & 2 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
from pandas.core.config import get_option

import pandas.plotting._core as gfx
import pandas.plotting.base as gfx_base

__all__ = ['Series']

Expand Down Expand Up @@ -3090,8 +3091,8 @@ def to_period(self, freq=None, copy=True):

# ----------------------------------------------------------------------
# Add plotting methods to Series
plot = accessor.AccessorProperty(gfx.SeriesPlotMethods,
gfx.SeriesPlotMethods)
plot = accessor.AccessorProperty(gfx_base.SeriesPlotMethods,
gfx_base.SeriesPlotMethods)
hist = gfx.hist_series


Expand Down
79 changes: 71 additions & 8 deletions pandas/plotting/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import numpy as np

from pandas.util._decorators import cache_readonly
from pandas.core.base import PandasObject
from pandas.core.dtypes.missing import isna, notna, remove_na_arraylike
from pandas.core.dtypes.common import (
is_list_like,
Expand All @@ -30,6 +29,7 @@
from pandas.io.formats.printing import pprint_thing
from pandas.util._decorators import Appender

from pandas.plotting import base
from pandas.plotting._compat import (_mpl_ge_1_3_1,
_mpl_ge_1_5_0,
_mpl_ge_2_0_0)
Expand Down Expand Up @@ -2458,16 +2458,66 @@ def _grouped_plot_by_column(plotf, data, columns=None, by=None,
return result


class BasePlotMethods(PandasObject):
class BokehSeriesPlotMethods(base.SeriesPlotMethods):

def __init__(self, data):
self._data = data
@property
def engine_name(self):
return 'bokeh'

def __call__(self, *args, **kwargs):
raise NotImplementedError
def __call__(**kwds):
import logging
logging.error(kwds)


class BokehFramePlotMethods(base.FramePlotMethods):
"""
repro notebook:

import pandas as pd
import numpy as np
import bokeh
from bokeh.io import output_notebook, INLINE

output_notebook(hide_banner=True)
pd.set_option('plotting.engine', 'bokeh')
df = pd.DataFrame(np.random.rand(5, 3), columns='foo bar baz'.split())
df.plot()
"""

@property
def engine_name(self):
return 'bokeh'

class SeriesPlotMethods(BasePlotMethods):
def __call__(self, x=None, y=None, kind='line', figure=None,
use_index=True, title=None, grid=None,
legend=True, style=None,
fontsize=None, colormap=None,
yerr=None, xerr=None,
secondary_y=False, sort_columns=False, **kwds):

from bokeh.plotting import Figure, show
from bokeh.models import ColumnDataSource, HoverTool

df = self._data
source = ColumnDataSource(df)
hover_tool = HoverTool(
tooltips=[
('index', '$index'),
('(x,y)', '($x, $y)'),
]
)
plot = Figure(
width=450,
height=300,
logo=None,
tools=[hover_tool]
)
for column in df.columns:
plot.line(x='index', y=column, source=source);
return show(plot)


class MPLSeriesPlotMethods(base.SeriesPlotMethods):
"""Series plotting accessor and method

Examples
Expand All @@ -2480,6 +2530,9 @@ class SeriesPlotMethods(BasePlotMethods):
with the ``kind`` argument:
``s.plot(kind='line')`` is equivalent to ``s.plot.line()``
"""
@property
def engine_name(self):
return 'matplotlib'

def __call__(self, kind='line', ax=None,
figsize=None, use_index=True, title=None, grid=None,
Expand Down Expand Up @@ -2624,7 +2677,7 @@ def pie(self, **kwds):
return self(kind='pie', **kwds)


class FramePlotMethods(BasePlotMethods):
class MPLFramePlotMethods(base.FramePlotMethods):
"""DataFrame plotting accessor and method

Examples
Expand All @@ -2637,6 +2690,9 @@ class FramePlotMethods(BasePlotMethods):
method with the ``kind`` argument:
``df.plot(kind='line')`` is equivalent to ``df.plot.line()``
"""
@property
def engine_name(self):
return 'matplotlib'

def __call__(self, x=None, y=None, kind='line', ax=None,
subplots=False, sharex=None, sharey=False, layout=None,
Expand Down Expand Up @@ -2844,3 +2900,10 @@ def hexbin(self, x, y, C=None, reduce_C_function=None, gridsize=None,
if gridsize is not None:
kwds['gridsize'] = gridsize
return self(kind='hexbin', x=x, y=y, C=C, **kwds)


base.register_engine("matplotlib", 'series', MPLSeriesPlotMethods)
base.register_engine("matplotlib", 'frame', MPLFramePlotMethods)

base.register_engine('bokeh', 'series', BokehSeriesPlotMethods)
base.register_engine('bokeh', 'frame', BokehFramePlotMethods)
96 changes: 96 additions & 0 deletions pandas/plotting/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
"""
Base module for plotting engines to override and register
with pandas.
"""
from pandas.core.base import PandasObject

engines = {}


def register_engine(name, kind, engine):
# XXX: get rid of the kind parameter
global engines
engines[(name, kind)] = engine


def deregister_engine(name, kind):
# XXX: get rid of the kind parameter
global engines
engines.pop((name, kind))


def get_engine(kind):
# XXX: get rid of the kind parameter
from pandas import get_option

active = get_option('plotting.engine')
if active == 'auto':
active = 'matplotlib'

return engines[(active, kind)]


class Dispatcher(object):

def __init__(self, data):
self._data = data

def __call__(self, *args, **kwargs):
kind = 'frame' if self._data.ndim == 2 else 'series'
engine = get_engine(kind)
return engine(self._data)(*args, **kwargs)

def __getattribute__(self, name):
if name == '_data':
return object.__getattribute__(self, name)
kind = 'frame' if self._data.ndim == 2 else 'series'

engine = get_engine(kind)(self._data)
return getattr(engine, name)


class BasePlotMethods(PandasObject):

def __init__(self, data):
self._data = data

def __call__(self, *args, **kwargs):
"""Make a plot"""
raise NotImplementedError

def area(self, **kwargs):
raise NotImplementedError("This backend doesn't support this method")

def bar(self, **kwargs):
raise NotImplementedError("This backend doesn't support this method")

def barh(self, **kwargs):
raise NotImplementedError("This backend doesn't support this method")

def box(self, **kwargs):
raise NotImplementedError("This backend doesn't support this method")

def density(self, **kwargs):
raise NotImplementedError("This backend doesn't support this method")

def hist(self, **kwargs):
raise NotImplementedError("This backend doesn't support this method")

def line(self, **kwargs):
raise NotImplementedError("This backend doesn't support this method")

def pie(self, **kwargs):
raise NotImplementedError("This backend doesn't support this method")


class SeriesPlotMethods(BasePlotMethods):
pass


class FramePlotMethods(BasePlotMethods):

def hexbin(self, x, y, **kwargs):
raise NotImplementedError("This backend doesn't support this method")

def scatter(self, x, y, **kwargs):
raise NotImplementedError("This backend doesn't support this method")