santosjorge / cufflinks

Productivity Tools for Plotly + Pandas
MIT License
3.03k stars 676 forks source link

How to display offline cufflink outputs on Github notebooks? #225

Open murilobellatini opened 4 years ago

murilobellatini commented 4 years ago

As far as I know, the feature to view plotted charts via cufflinks within a static GitHub notebook is not available (offline mode meant here). Is there a workaround to get the iplot() to return a static image on the IPython Shell so it's visible on notebooks viewed via GitHub?

This is very frustrating for cufflinks to be such an amazing visualization tool, which cannot be easily shared amongst other Data Scientists, Analysts and stakeholders in general...

References

timkpaine commented 4 years ago

Cufflinks relies on plotly, so there is nothing we can offer here that is not already said on the plotly issue

murilobellatini commented 4 years ago

Hi @timkpaine, I found a workaround shown here: https://community.plot.ly/t/create-static-plotly-figure-in-jupyter-with-python/16413

 figured out how to do this. First

import plotly.io as pio
from IPython.display import Image
Then, if the plotly figure is stored in fig, you can display a static rendering inline in Jupyter with

Image(pio.to_image(fig, format='png'))
Reference link: https://plot.ly/python/static-image-export/ 36

Do you know the latest compatible versioning of cufflinks and plotly with io.to_image method? I couldn't get this working on my last try.

timkpaine commented 4 years ago

if you pass in asFigure=True you'll get back a figure object you can use in the same way as that example

murilobellatini commented 4 years ago

@timkpaine, I tried that already and it returns None... I'm working on cufflinks v0.13.0 and plotly v2.7.0 which were the only compatible versioning I was able get functioning from conda.

timkpaine commented 4 years ago

we can only fix bugs in the latest versions, you should be able to pip install alongside conda.

nicolaskruchten commented 4 years ago

Using plotly v4+ and cufflinks v0.17+ you should be able to use the approach I just posted about in https://github.com/plotly/plotly.py/issues/931 if you use asFigure=True

murilobellatini commented 4 years ago

@nicolaskruchten, I was able to implement a not so practical workaround via the function below.

My first approach was to implement a decorator which forces the asFigure and dimensions arguments, and renders the plotly.Figure to IPython Shell Image. I wasn't able though for iplot being a bound method of cufflinks/pandas.

Do you have any suggestions for a cleaner approach?

Thanks.

def static_plot(img_figure:Figure):
    """
    Plots to IPython Shell cufflinks chart as static images.

    `img_figure`: plotly Figure class with chart as json.

    Required `.iplot` arguments :
    - asFigure:bool=True
    - dimensions:(int,int)=(1400,600)

    E.g.:
    > img_figure = df.iplot(*args, asFigure=True, dimensions=(1400,600))
    """
    img_serialized = to_image(img_figure)
    img_static = Image(img_serialized)
    return img_static
nicolaskruchten commented 4 years ago

have you tried just img_figure.show("svg") ?

nicolaskruchten commented 4 years ago

Check out the cufflinks examples at the bottom here: https://github.com/nicolaskruchten/plotly_img_test/blob/master/Untitled.ipynb

The way this works is that in addition to .iplot(), cufflinks adds a .figure() function to data frames, which is the same as .iplot() except that it sets asFigure=true, meaning it returns a full Plotly.py go.Figure object, which has all the renderer system attached to .show(). In a notebook context, this will inline the output in the notebook if you use the svg or png renderers, meaning that when you upload a notebook to Github, it will render. You can also set the renderer globally for the notebook using

import plotly.io as pio
pio.renderers.default = "svg"

so that you don't even need to pass "svg" to .show() any more, and in fact you can just have the figure be the final line in the cell and let the Notebook use the default rendering pipeline.

murilobellatini commented 4 years ago

It worked. Awesome! Much better and straighforward like this...