holoviz / hvplot

A high-level plotting API for pandas, dask, xarray, and networkx built on HoloViews
https://hvplot.holoviz.org
BSD 3-Clause "New" or "Revised" License
1.09k stars 105 forks source link

step plot broken when using streaming dataframe #502

Open limx0 opened 4 years ago

limx0 commented 4 years ago

Hi,

I'd just like to report that it appears the step plot doesn't work with streaming dataframes.

ALL software version info

(this library, plus any other relevant software, e.g. bokeh, python, notebook, OS, browser, etc) Latest versions of the main libraries (I also tried some older versions of hvplot because I believe this has worked in the past but couldn't find any combination that worked in my brief attempts)

Name: hvplot
Version: 0.6.0

Name: holoviews
Version: 1.13.3

Name: streamz
Version: 0.5.5

Name: bokeh
Version: 2.1.1

Description of expected behavior and the observed behavior

Step plot should work or hvplot should raise a more informative exception (step plot not allowed with streaming dataframes?)

Complete, minimal, self-contained example code that reproduces the issue

import pandas as pd
from streamz import Stream
import hvplot.streamz

s = Stream() 
sdf = s.to_dataframe(example=pd.DataFrame(columns=['x', 'y']))
sdf.hvplot.step()  # replace with any other plot type works fine

Stack traceback and/or browser JavaScript console output

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
./venv/lib/python3.8/site-packages/IPython/core/formatters.py in __call__(self, obj, include, exclude)
    968 
    969             if method is not None:
--> 970                 return method(include=include, exclude=exclude)
    971             return None
    972         else:

./venv/lib/python3.8/site-packages/holoviews/core/dimension.py in _repr_mimebundle_(self, include, exclude)
   1310         combined and returned.
   1311         """
-> 1312         return Store.render(self)
   1313 
   1314 

./venv/lib/python3.8/site-packages/holoviews/core/options.py in render(cls, obj)
   1393         data, metadata = {}, {}
   1394         for hook in hooks:
-> 1395             ret = hook(obj)
   1396             if ret is None:
   1397                 continue

./venv/lib/python3.8/site-packages/holoviews/ipython/display_hooks.py in pprint_display(obj)
    280     if not ip.display_formatter.formatters['text/plain'].pprint:
    281         return None
--> 282     return display(obj, raw_output=True)
    283 
    284 

./venv/lib/python3.8/site-packages/holoviews/ipython/display_hooks.py in display(obj, raw_output, **kwargs)
    256     elif isinstance(obj, (HoloMap, DynamicMap)):
    257         with option_state(obj):
--> 258             output = map_display(obj)
    259     elif isinstance(obj, Plot):
    260         output = render(obj)

./venv/lib/python3.8/site-packages/holoviews/ipython/display_hooks.py in wrapped(element)
    144         try:
    145             max_frames = OutputSettings.options['max_frames']
--> 146             mimebundle = fn(element, max_frames=max_frames)
    147             if mimebundle is None:
    148                 return {}, {}

./venv/lib/python3.8/site-packages/holoviews/ipython/display_hooks.py in map_display(vmap, max_frames)
    204         return None
    205 
--> 206     return render(vmap)
    207 
    208 

./venv/lib/python3.8/site-packages/holoviews/ipython/display_hooks.py in render(obj, **kwargs)
     66         renderer = renderer.instance(fig='png')
     67 
---> 68     return renderer.components(obj, **kwargs)
     69 
     70 

./venv/lib/python3.8/site-packages/holoviews/plotting/renderer.py in components(self, obj, fmt, comm, **kwargs)
    386                 doc = Document()
    387                 with config.set(embed=embed):
--> 388                     model = plot.layout._render_model(doc, comm)
    389                 if embed:
    390                     return render_model(model, comm)

./venv/lib/python3.8/site-packages/panel/viewable.py in _render_model(self, doc, comm)
    416         if comm is None:
    417             comm = state._comm_manager.get_server_comm()
--> 418         model = self.get_root(doc, comm)
    419 
    420         if config.embed:

./venv/lib/python3.8/site-packages/panel/viewable.py in get_root(self, doc, comm)
    645         """
    646         doc = doc or _curdoc()
--> 647         root = self._get_model(doc, comm=comm)
    648         self._preprocess(root)
    649         ref = root.ref['id']

./venv/lib/python3.8/site-packages/panel/layout.py in _get_model(self, doc, root, parent, comm)
    118         if root is None:
    119             root = model
--> 120         objects = self._get_objects(model, [], doc, root, comm)
    121         props = dict(self._init_properties(), objects=objects)
    122         model.update(**self._process_param_change(props))

./venv/lib/python3.8/site-packages/panel/layout.py in _get_objects(self, model, old_objects, doc, root, comm)
    108             else:
    109                 try:
--> 110                     child = pane._get_model(doc, root, model, comm)
    111                 except RerenderError:
    112                     return self._get_objects(model, current_objects[:i], doc, root, comm)

./venv/lib/python3.8/site-packages/panel/pane/holoviews.py in _get_model(self, doc, root, parent, comm)
    225             plot = self.object
    226         else:
--> 227             plot = self._render(doc, comm, root)
    228 
    229         plot.pane = self

./venv/lib/python3.8/site-packages/panel/pane/holoviews.py in _render(self, doc, comm, root)
    284             kwargs = {}
    285 
--> 286         return renderer.get_plot(self.object, **kwargs)
    287 
    288     def _cleanup(self, root):

./venv/lib/python3.8/site-packages/holoviews/plotting/bokeh/renderer.py in get_plot(self_or_cls, obj, doc, renderer, **kwargs)
     71         combining the bokeh model with another plot.
     72         """
---> 73         plot = super(BokehRenderer, self_or_cls).get_plot(obj, doc, renderer, **kwargs)
     74         if plot.document is None:
     75             plot.document = Document() if self_or_cls.notebook_context else curdoc()

./venv/lib/python3.8/site-packages/holoviews/plotting/renderer.py in get_plot(self_or_cls, obj, doc, renderer, comm, **kwargs)
    235             init_key = tuple(v if d is None else d for v, d in
    236                              zip(plot.keys[0], defaults))
--> 237             plot.update(init_key)
    238         else:
    239             plot = obj

./venv/lib/python3.8/site-packages/holoviews/plotting/plot.py in update(self, key)
    898     def update(self, key):
    899         if len(self) == 1 and ((key == 0) or (key == self.keys[0])) and not self.drawn:
--> 900             return self.initialize_plot()
    901         item = self.__getitem__(key)
    902         self.traverse(lambda x: setattr(x, '_updated', True))

./venv/lib/python3.8/site-packages/holoviews/plotting/bokeh/element.py in initialize_plot(self, ranges, plot, plots)
   2221             if self.tabs:
   2222                 subplot.overlaid = False
-> 2223             child = subplot.initialize_plot(ranges, plot, plots)
   2224             if isinstance(element, CompositeOverlay):
   2225                 # Ensure that all subplots are in the same state

./venv/lib/python3.8/site-packages/holoviews/plotting/bokeh/element.py in initialize_plot(self, ranges, plot, plots, source)
   1337         self.handles['plot'] = plot
   1338 
-> 1339         self._init_glyphs(plot, element, ranges, source)
   1340         if not self.overlaid:
   1341             self._update_plot(key, plot, style_element)

./venv/lib/python3.8/site-packages/holoviews/plotting/bokeh/element.py in _init_glyphs(self, plot, element, ranges, source)
   1281         else:
   1282             style = self.style[self.cyclic_index]
-> 1283             data, mapping, style = self.get_data(element, ranges, style)
   1284             current_id = element._plot_id
   1285 

./venv/lib/python3.8/site-packages/holoviews/plotting/bokeh/chart.py in get_data(self, element, ranges, style)
    359 
    360         if 'steps' in self.interpolation:
--> 361             element = interpolate_curve(element, interpolation=self.interpolation)
    362         data = {x: element.dimension_values(xidx),
    363                 y: element.dimension_values(yidx)}

./venv/lib/python3.8/site-packages/param/parameterized.py in __new__(class_, *args, **params)
   2810         inst = class_.instance()
   2811         inst.param._set_name(class_.__name__)
-> 2812         return inst.__call__(*args,**params)
   2813 
   2814     def __call__(self,*args,**kw):

./venv/lib/python3.8/site-packages/holoviews/core/operation.py in __call__(self, element, **kwargs)
    197         kwargs['per_element'] = self._per_element
    198         kwargs['link_dataset'] = self._propagate_dataset
--> 199         return element.apply(self, **kwargs)
    200 
    201 

./venv/lib/python3.8/site-packages/holoviews/core/accessors.py in pipelined_call(*args, **kwargs)
     43 
     44             try:
---> 45                 result = __call__(*args, **kwargs)
     46 
     47                 if not in_method:

./venv/lib/python3.8/site-packages/holoviews/core/accessors.py in __call__(self, apply_function, streams, link_inputs, link_dataset, dynamic, per_element, **kwargs)
    202             if hasattr(apply_function, 'dynamic'):
    203                 inner_kwargs['dynamic'] = False
--> 204             new_obj = apply_function(self._obj, **inner_kwargs)
    205             if (link_dataset and isinstance(self._obj, Dataset) and
    206                 isinstance(new_obj, Dataset) and new_obj._dataset is None):

./venv/lib/python3.8/site-packages/holoviews/core/operation.py in __call__(self, element, **kwargs)
    192             elif ((self._per_element and isinstance(element, Element)) or
    193                   (not self._per_element and isinstance(element, ViewableElement))):
--> 194                 return self._apply(element)
    195         elif 'streams' not in kwargs:
    196             kwargs['streams'] = self.p.streams

./venv/lib/python3.8/site-packages/holoviews/core/operation.py in _apply(self, element, key)
    130 
    131         element_pipeline = getattr(element, '_pipeline', None)
--> 132         ret = self._process(element, key)
    133 
    134         for hook in self._postprocess_hooks:

./venv/lib/python3.8/site-packages/holoviews/operation/element.py in _process(self, element, key)
    965 
    966     def _process(self, element, key=None):
--> 967         return element.map(self._process_layer, Element)
    968 
    969 

./venv/lib/python3.8/site-packages/holoviews/core/data/__init__.py in pipelined_fn(*args, **kwargs)
    214 
    215             try:
--> 216                 result = method_fn(*args, **kwargs)
    217 
    218                 op = method_op.instance(

./venv/lib/python3.8/site-packages/holoviews/core/data/__init__.py in map(self, *args, **kwargs)
   1181 
   1182     def map(self, *args, **kwargs):
-> 1183         return super(Dataset, self).map(*args, **kwargs)
   1184     map.__doc__ = LabelledData.map.__doc__
   1185 

./venv/lib/python3.8/site-packages/holoviews/core/dimension.py in map(self, map_fn, specs, clone)
    703             return deep_mapped
    704         else:
--> 705             return map_fn(self) if applies else self
    706 
    707 

./venv/lib/python3.8/site-packages/holoviews/operation/element.py in _process_layer(self, element, key)
    959             x = x.astype(dt_type)
    960         dvals = tuple(element.dimension_values(d) for d in element.dimensions()[1:])
--> 961         xs, dvals = INTERPOLATE_FUNCS[self.p.interpolation](x, dvals)
    962         if is_datetime:
    963             xs = xs.astype(dt_type)

./venv/lib/python3.8/site-packages/holoviews/operation/element.py in pts_to_midstep(cls, x, values)
    921 
    922         steps[1:-1:2] = steps[2::2] = x[:-1] + (x[1:] - x[:-1])/2
--> 923         steps[0], steps[-1] = x[0], x[-1]
    924 
    925         val_arrays = []

IndexError: index 0 is out of bounds for axis 0 with size 0

Screenshots or screencasts of the bug in action

jlstevens commented 4 years ago

Definitely a bug as it should work and used to work. Assigning to the next milestone.