3

I have Anaconda 3.7 installed on Windows. It works in Jupyter but not in Spyder. This code:

import holoviews as hv
import pandas as pd
import numpy as np
output_notebook ()
flora = pd.read_csv ('iris.csv')
hv.extension('bokeh')
frequencies, edges = np.histogram(flora['petal width'], bins = 5)
print(frequencies, edges)
hv.Histogram(frequencies, edges, label = 'Histogram')

returns only values:

[49  8 41 29 23] [0.1  0.58 1.06 1.54 2.02 2.5 ]
WARNING:root:Histogram: Histogram edges should be supplied as a tuple along with the values, passing the edges will be deprecated in holoviews 2.0.

Is it possible to see histogram in Spyder?

Joys
  • 311
  • 3
  • 15
  • You can use `matplotlib` to plot the histogram. Read [this](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.hist.html) – Sheldore Mar 17 '19 at 14:31
  • @Bazingaa thank you for your answer. I know that `matplotlib` could draw it. I'm just trying to understand how to use PyViz in Spyder. – Joys Mar 17 '19 at 14:41
  • 1
    It might be helpful to rename this question to being about displaying any HoloViews output in Spyder, as I don't think it's specifically an issue with histograms. – James A. Bednar Mar 19 '19 at 13:49

4 Answers4

5

(Spyder maintainer here) Holoviews produces content to be rendered in a web browser and Spyder consoles are not able to display that content at the moment, sorry.

Carlos Cordoba
  • 33,273
  • 10
  • 95
  • 124
5

As a workaround, you can open your graph in your browser by putting your Holoviews graph in a Panel object and calling .show() on it.
Library Panel can be used to create a dashboard with Holoviews graphs in your browser.
Here's a working example:

# library imports
import numpy as np
import pandas as pd
import holoviews as hv
hv.extension('bokeh', logo=False)
import panel as pn

# create sample data
data = np.random.normal(size=[50, 2])
df = pd.DataFrame(data, columns=['col1', 'col2'])

# create holoviews graph
hv_plot = hv.Points(df)

# display graph in browser
# a bokeh server is automatically started
bokeh_server = pn.Row(hv_plot).show(port=12345)

# stop the bokeh server (when needed)
bokeh_server.stop()

See also:
https://stackoverflow.com/questions/57971107/how-do-i-get-my-interactive-holoviews-graph-to-display-in-visual-studio-without/[][1]

Alternatively you can set bokeh as backend of the renderer and then use bokeh.render.show(). This will open your holoviews plot in the browser:

import holoviews as hv
hv.extension('bokeh')
from bokeh.plotting import show

show(hv.render(your_holoviews_plot))
Sander van den Oord
  • 10,986
  • 5
  • 51
  • 96
5

The beauty of holoviews is that it allows you to choose between the modern browser-based bokeh and the good-old familiar matplotlib to display its plots (as well as plotly to some extend, mainly for 3D plots).

Spyder is able to render matplotlib plots either inline (i.e. in the python console itself or since recently is their new plots panel) or interactively (i.e. in a pop up window - several backends exist, amongst all qt). You can switch between these by typing %matplotlib inline or %matplotlib qt in your spyder ipython console.

These backends will then be the place where your holoview-generated matplotlib plots land!

Now, you need to explicitly tell holoviews to use matplotlib as a backend to render plots (what I refer to below as holoview_object can be either what they call an 'element' or a combination of these: layout, overlay, holomap...). You can do it using

matplotlib_fig = holoviews.render(holoview_object, backend='matplotlib')

and then create an empty matplotlib figure and hack its manager to display it in your default matplotlib backend:

dummy = plt.figure()
new_manager = dummy.canvas.manager
new_manager.canvas.figure = matplotlib_fig
fig.set_canvas(new_manager.canvas)

Using the concepts above, I made myself some utility functions to easily display matplotlib or bokeh plots from within spyder, directly or starting with a holoviews object, feel free to use them:

import matplotlib.pyplot as plt
import bokeh as bk
import holoviews as hv

def mplshow(fig):

    # create a dummy figure and use its
    # manager to display "fig"

    dummy = plt.figure()
    new_manager = dummy.canvas.manager
    new_manager.canvas.figure = fig
    fig.set_canvas(new_manager.canvas)

def bkshow(bkfig, title=None, save=0, savePath='~/Downloads'):
    if title is None: title=bkfig.__repr__()
    if save:bk.plotting.output_file(f'{title}.html')
    bk.plotting.show(bkfig)

def hvshow(hvobject, backend='matplotlib', return_mpl=True):
    '''
    Holoview utility which
    - for dynamic display, interaction and data exploration:
        in browser, pops up a holoview object as a bokeh figure
    - for static instanciation, refinement and data exploitation:
        in matplotlib current backend, pops up a holoview object as a matplotlib figure
        and eventually returns it for further tweaking.
    Parameters:
        - hvobject: a Holoviews object e.g. Element, Overlay or Layout.
        - backend: 'bokeh' or 'matplotlib', which backend to use to show figure
        - return_mpl: bool, returns a matplotlib figure
        
    '''
    assert backend in ['bokeh', 'matplotlib']
    if backend=='matplotlib' or return_mpl:
        mplfig=hv.render(hvobject, backend='matplotlib')
    if backend=='bokeh': bkshow(hv.render(hvobject, backend='bokeh'))
    elif backend=='matplotlib': mplshow(mplfig)
    if return_mpl: return mplfig

In summary: if you wish to render your plot statically in the spyder plot pane (or the python console if you do not use their plot pane), do:

%matplotlib inline
hvshow(holoviews_object, 'matplotlib')

if you wish to pop up your plot in an interactive qt window, do:

%matplotlib qt
hvshow(holoviews_object, 'matplotlib')

if you wish to pop up your plot in your browser (i.e. with bokeh), also interactively, do:

hvshow(holoviews_object, 'bokeh')

I love spyder (much more than jupyter notebooks) as much as holoviews and I am thrilled to be able to use both together!

Maxime Beau
  • 688
  • 10
  • 6
0

Regarding the answer from Maxime Beau, I had to modify the bkshow() utility function to work in Spyder. Basically, I just had to set the function to save by default; I also added savePath functionality. See the following thread for an explanation https://github.com/spyder-ide/spyder/issues/21099

def bkshow(bkfig, title=None, save=1, savePath='./bokeh'):
    savePath = os.path.join(savePath,'')
    if not os.path.exists(savePath):
        os.makedirs(savePath)
    if title is None: title=bkfig.__repr__()
    if save: bk.plotting.output_file(f'{savePath}{title}.html')
    bk.plotting.show(bkfig)
Marcus
  • 1