Skip to content

Instantly share code, notes, and snippets.

@So-Cool
Created June 30, 2017 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save So-Cool/8c511b05e9800320d6ab6c502bf57a89 to your computer and use it in GitHub Desktop.
Save So-Cool/8c511b05e9800320d6ab6c502bf57a89 to your computer and use it in GitHub Desktop.
HighCharts in Jupyter
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@perellonieto
Copy link

I added the option to pass strings as datetimes and then parse them to visualize in the stockChart.

from IPython.core.display import display, HTML
import random
from datetime import datetime
from dateutil.parser import parse

epoch = datetime.utcfromtimestamp(0).replace(tzinfo=None)


def unix_time_miliseconds(dt):
    return (dt.replace(tzinfo=None) - epoch).total_seconds() * 1000.0


def high(time, data, title="title", xax="X", yax="Y", chart="high_chart"):
    if len(time) != len(data):
        print "Length of time and data must agree"
        return None

    if chart == "high_chart":
        a = "Highcharts.chart"
        b = "type: 'linear'"
    elif chart == "high_stock":
        a = "Highcharts.stockChart"
        b = "type: 'datetime', ordinal: false"
        if len(time) > 0 and type(time[0]) is str:
            time = [unix_time_miliseconds(parse(dt)) for dt in time]
    else:
        raise(KeyError('Invalid key: {}'.format(type)))

        
    r = str(random.randint(0,10000))
        
    template = """
        <html>
        <head>
        <title>%s</title>
           <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
           <script src="https://code.highcharts.com/stock/highstock.js"></script>
           <script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
        </head>
        <body>

        <div id="container%s" style="width: 800px; height: 600px; margin: 125 auto"></div>

        <script language="JavaScript">
               var data = %s;

            %s('container%s', {
                chart: {
                    zoomType: 'x'
                },
                title: {
                    text: '%s'
                },
                subtitle: {
                    text: document.ontouchstart === undefined ?
                            'Click and drag in the plot area to zoom in' : 'Pinch the chart to zoom in'
                },
                xAxis: {
                    %s
                },
                yAxis: {
                    title: {
                        text: '%s'
                    }
                },
                legend: {
                    enabled: false
                },
                series: [{
                    type: 'spline',
                    name: '%s',
                    data: data
                }]
            });
        </script>

        </body>
        </html>

    """

    d = [[i,j] for i, j in zip(time, data)]
    d = str(d)
    f = template % (title, r, d, a, r, title, b, yax, yax)
    
    display(HTML(f))

Then the following time format should work

high(['2001-01-08', 'July 2004', '3rd May 2014'], [0,3,2], chart="high_stock")

@perellonieto
Copy link

I created a version that would work for multiple time series for the StockChart. It needs to be cleaned and rethought, but it is working for the plots that I needed.

def plot_multiple_stock(data, time=None, names=None, htype=None, title='title', ylabel='Y'):
    """
    Parameters
    ----------
    data : - list of list of numbers
        or - list of dictionaries. In this case, the other parameters time, names and htype are ignored.
               Each dictionary needs to contain an entry 'data' and other possible entries accepted by 
               highcharts. Some examples are:
                  'data' : y value for each point
                  'time' : x value for each point of data
                  'name' : name of the serie
                  'type' : type of line ('spline', 'line')
    time : - list of list of numbers
        or - list of numbers
    """
    if isinstance(data, list) and isinstance(data[0], dict):
        seriesOptions = data
    else:
        if names is not None:
            assert(len(data) == len(names))
        if htype is not None:
            if isinstance(htype, list):
                assert(len(data) == len(htype))

        seriesOptions = []
        for i, serie_data in enumerate(data):
            serie = {}
            if time is not None:
                if isinstance(time[i], list):
                    serie_time = time[i]
                else:
                    serie_time = time
                if len(serie_time) > 0 and type(serie_time[0]) is str:
                    serie_time = [unix_time_miliseconds(parse(dt)) for dt in serie_time]
                serie['data'] = [list(a) for a in zip(serie_time, serie_data)]
            else:
                print('there is no time')
                serie['data'] = serie_data
            if htype is not None:
                if isinstance(htype, list):
                    serie['type'] = htype[i]
                else:
                    serie['type'] = htype
            if names is not None:
                if len(names) > 0:
                    serie['name'] = names[i]
                else:
                    serie['name'] = names
            seriesOptions.append(serie)
    
    template = """
     <html>
        <head>
        <title>highchart</title>
           <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
           <script src="https://code.highcharts.com/stock/highstock.js"></script>
           <script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
        </head>
        <body>

        <div id="container%s" style="width: 800px; height: 600px; margin: 125 auto"></div>

        <script language="JavaScript">
            var seriesOptions = %s;

            /**
             * Create the chart when all data is loaded
             * @returns {undefined}
             */
            Highcharts.stockChart('container%s', {
                chart: {
                    zoomType: 'x'
                },
              title: {
                  text: '%s'
              },
              plotOptions: {
                series: {
                  showInNavigator: true,
                }
              },
                yAxis: {
                    title: {
                        text: '%s'
                    }
                },
              tooltip: {
                pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b>',
                valueDecimals: 2,
                split: true
              },
              series: seriesOptions
            });
        </script>

        </body>
        </html>
    """
    
    r = str(random.randint(0,10000))
    f = template % (r, seriesOptions, r, title, ylabel)
    
    display(HTML(f))

It can be called in various ways. One way is to pass a list of dictiionaries with all the data, in the same format that is expected by highcharts seriesOptions.

seriesOptions = [dict(name='data1', data=[9,5,7,2], type='spline'),
                 dict(name='data2', data=[2,7,3,8], type='spline'),
                 dict(name='data3', data=[3,1,3,1], type='line'),
                 dict(name='data4', data=[0,5,0,5], type='line')]
        
plot_multiple_stock(seriesOptions, title='test multi-output', ylabel='meters')

You can specify the individual time per each of the time series as well. E.g:

for i in range(len(seriesOptions)):
    data = seriesOptions[i]['data']
    for j, k in enumerate(data):
        data[j] = [j+i*1e10+99e10, k]
    seriesOptions[i]['data'] = data

plot_multiple_stock(seriesOptions, title='test multi-output', ylabel='meters')

Or you can give all the parameters separated, with common time values for all the series or different ones. E.g:

time = [[0,1,2,3],
        ['2/03/1999', '3/4/2001', 'Sept 2003', '3rd Aug 2005'],
        [0,1,2,3],
        ['May 2012', 'Jul 2014', 'Aug 2016', 'Dec 2016']]
data = [[9,5,7,2],
        [0, 5, 7, 2],
        [2, 7, 3, 8],
        [0, 5, 0, 5]]
htype= ['spline', 'line', 'spline', 'line']
names = ['data1', 'data2', 'data3', 'data4']
        
plot_multiple_stock(data, time=time, names=names, htype=htype, title='test multi-output', ylabel='meters')

As I said, the code should be cleaned. I hope it is useful.

Regards,

@sada-narayanappa
Copy link

This does not work - not sure why! this use to work once

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment