Working with Series in Highcharts for Python


Highcharts for Python (and Highcharts (JS), of course) are both built around the concept of data series. A data series can be thought of as a set of data points that describe the same “thing”, and which represent how the data can be organized. Think:

  • a single line on a line chart

  • a set of columns all the same color on a column chart

  • all of a pie or donut chart

As a result, when you constructing your chart in Highcharts for Python, what you are really doing is constructing one or more series that are then placed on a shared canvas, with shared axes, a shared legend, etc.

Diagram showing the conceptual components of a Highcharts chart

This tutorial is designed to help you understand how to manage series in your Highcharts visualizations using Highcharts for Python.


How Series are Organized

As the diagram above shows, Highcharts visualizations are configured within a Chart object, which has the .options property where the chart’s configuration “lives”, represented as a HighchartsOptions instance.

The HighchartsOptions configuration allows you to define all details of what gets displayed on the chart, how that content behaves, etc. The configuration options available in HighchartsOptions can be thought of as chart-level configurations: They configure or define things that apply to everything shown on the chart: the axes to display, the legend, the title, the settings shared across all of the series on the chart, etc.

But within the HighchartsOptions you will find the .series property. This is where you define the specific series to render on your chart.

This property gets one or more series instances, all of which are descended from SeriesBase. They descend from this single base series class because many of their properties are shared across all types of series. For example, whether the series is to render as a line or as a bar, all series will have an .id option.

All visualizations supported by Highcharts have a corresponding series type, which means they all have their corresponding series class. To see this mapping, take a look at our Supported Visualizations.

Each series type has its set of shared properties that derive from SeriesBase will have options to configure the gauge’s dial (.dial), overshot-handling (.overshoot), and pivot point (.pivot) - settings which would be completely irrelevant for a LineSeries, which does not have a dial, does not have a concept of overshooting the bounds of the dial, and does not have any pivot points.

Gauge Example Chart
Line Example Chart

And all series (technically, almost all) have a .data property, which contains the data that should be visualized in the series.

So as you can see, series are pretty fundamental to your Highcharts visualizations: They are what actually gets visualized.

So how do we start creating series using Highcharts for Python?


Creating Series in Highcharts for Python

Of course, you can always construct your series using direct instantiation:

from highcharts_gantt.chart import Chart
from highcharts_gantt.options import HighchartsOptions
from highcharts_gantt.options.series.area import LineSeries

my_line_series = LineSeries(data = my_data, id = 'my_series_id123')
my_options = HighchartsOptions(series = [my_line_series])
my_chart = Chart(options = my_options)

And there may be situations where there is the best way for you to construct your series, depending on how you are managing your full Highcharts for Python application.

But there are much simpler / faster ways to rapidly create your chart/series:

Assembling a Chart with Series at Once

my_chart = Chart(data = my_iterable, series_type = 'line')

This will create a Chart instance with one series of type line (represented as a LineSeries instance).

Depending on how we’ve wrangled our data, we can similarly produce a chart from a pandas.DataFrame, numpy.ndarray, or Python dict:

# From a Pandas DataFrame

my_chart = Chart.from_pandas(df, series_type = 'line')

# From a Numpy ndarray

my_chart = Chart.from_array(as_ndarray, series_type = 'line')

# From a Python dict

my_chart = Chart(data = as_dict, series_type = 'line')

All of these lines of code are equivalent, and should produce an identical my_chart.

Assembling Series Alone

You can create series similarly:

from highcharts_gantt.options.series.area import LineSeries

my_line_series = LineSeries(data = my_iterable)

This will create a LineSeries instance.

Depending on how we’ve wrangled our data, we can similarly produce one or more series from a pandas.DataFrame, numpy.ndarray, or Python dict:

# From a Pandas DataFrame

my_series = LineSeries.from_pandas(df)

# From a Numpy ndarray

my_series = LineSeries.from_array(data = as_ndarray)

# From a CSV file

my_series = LineSeries.from_csv('my-data.csv')

# From a Python iterable

my_series = LineSeries.from_array(data = as_iterable)

All of these lines of code are equivalent, and should produce an identical my_series. Depending on the arguments you supply to the helper methods, they may either produce one series instance or a list of series instances.

Adding Series to a Chart

If you have created series on their own, you can add them to an existing Chart very easily:

# EXAMPLE 1.
# Adding one series

my_chart.add_series(my_series)

# EXAMPLE 2.
# Adding multiple series if they are in one iterable

my_chart.add_series(my_list_of_series)

# EXAMPLE 3.
# Adding multiple individual series

my_chart.add_series(series1, series2, series3)

Or you can also create a new chart from a list of series:

# EXAMPLE 1.
# With one series

my_chart = Chart.from_series(my-series)

# EXAMPLE 2.
# With multiple series if they are in one iterable

my_chart = Chart.from_series(my_list_of_series)

# EXAMPLE 3.
# Adding multiple individual series

my_chart = Chart.from_series(series1, series2, series3)

Tip

The same .add_series and .from_series helper methods are also available on the HighchartsOptions class.

So now that we’ve created a chart and a bunch of series, what else can we do?


Configuring Your Series

You can configure the options available on each series very simply. Highcharts (JS) - and so Highcharts for Python - have a very extensive API, with lots of configuration options.

Tip

We recommend reviewing the API Reference to really explore the options available for different series types.

Updating Data Points

However, the most important configuration you will do is to manage the data points you wish to display in your series. You can do this by:

  1. Passing data directly to the .data property:

    my_series.data = updated_data
    
  2. Using any of the helper methods provided on the series instance:

    # EXAMPLE 1.
    # Updating data points from a new Pandas DataFrame
    
    my_series.load_from_pandas(df)
    
    # EXAMPLE 2.
    # Updating data points from a new numpy.ndarray
    
    my_series.load_from_array(as_ndarray)
    
    # EXAMPLE 3.
    # Updating data points from a new iterable.
    
    my_series.load_from_array(as_iterable)
    
    # EXAMPLE 4.
    # Updating data points from a CSV file.
    
    my_series.load_from_csv('my-updated-csv-file.csv')
    

Updating Data Point Properties

In addition, all series instances make it easy to propagate information throughout your underlying data. When you try to set a property on your series object, Highcharts for Python will first see if it is a valid property on the series itself. But if it is not, then it will check whether it is a supported property on that series’ data.

So as an example, if we want to give our series an ID, we can simply call:

my_series.id = 'my-updated-id-value'

However, if we want to set a BulletSeries data points’ .target value, we can simply reference it on the series. For example, if our BulletSeries contains three data points, we can set their targets easily using the series:

my_bullet_series.target = [1, 2, 3]

By passing an iterable (or a numpy.ndarray), all of your data points will get updated with the appropriate value. This makes it very easy to execute your data point configurations by operating on the series, rather than working with individual data points - though if you want to work with individual data points, you can do so as well.

Converting Series Types

Every series type has its own type-specific set of configuration options. However, there may be times when you want to change how your data is to be visualized / rendered. Highcharts for Python provides a useful helper method for that, too. For example, if we want to convert our LineSeries to a BarSeries, we can do that by calling the .convert_to method:

# EXAMPLE 1
# Indicating the target type with a string label

my_series.convert_to(series_type = 'bar')

# EXAMPLE 2
# Indicating the target type with a SeriesBase class

my_series.convert_to(series_type = BarSeries)

So now that we’ve constructed, configured, and adjusted our series, we can also render them easily.


Rendering Series

Series can be rendered within the chart that they are a part of, simply by following the process to render the chart:

Rendering a Series within a Chart

  1. When in Jupyter Notebook/Lab, just execute the .display() method.

    my_chart.display()
    
  2. When rendering within a web application, or saving to a file for rendering in a separate application, you can serialize your chart to JavaScript object literal notation:

    as_js_literal = my_chart.to_js_literal()
    

    which will produce the JavaScript code to render your complete chart.

Rendering a Series Alone

The exact same helper methods are available on your series as well. So if you have assembled your series as my_series, you can take a shortcut to visualize it by calling:

my_series.display()

which will assemble a generic Chart instance, include your series, and render it in Jupyter Notebook/Lab.

You can also produce a Chart instance containing your series in a single method call as well:

my_chart = my_series.to_chart()

And similarly:

series_as_js_literal = my_series.to_js_literal()

will produce the JS literal representation of your series, for use in a JavaScript application.


Given all of this flexibliity, we hope you have a great time assembling high-end visualizations and exploring Highcharts for Python!