c3py is a Python wrapper around c3js (http://c3js.org/).
c3js has a function named generate, which takes a JSON object as input, and generates a chart which is bound to a specified <div> element. The basic premise of c3py is to build a Python dictionary, which is then converted to a JSON object using json.dumps, and passed to c3.generate().
This works particularly well with Jupyter notebooks, where the HTML function from IPython.display can be used to display the interactive chart inline.
First, import c3py and HTML (from IPython.display).
In [1]:
import c3py
from IPython.display import HTML
Create an instance of the Chart class, providing the chart's name as the lone argument. The name will be the ID of the <div> which contains that chart, i.e. two charts in the same document should not have the same name.
In [2]:
chart_one = c3py.Chart('chart_one')
The chart contains a data object, which has functions analogous to c3js' different chart types. These include:
Each of these functions takes, as arguments, x and y, which are lists of values, and label, which is a string defining the name of the series.
In [3]:
chart_one.data.line(x=range(1, 6), y=range(10, 60, 10), label='series_one')
Once data has been added, the chart can be displayed in a notebook using the HTML function imported earlier. Alternatively, c3py can be used in a web application, and the HTML string can be passed to the front-end template.
In [4]:
HTML(chart_one.get_html_string())
Out[4]:
In [5]:
line_chart = c3py.Chart('line_chart')
line_chart.data.line(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='line')
line_chart.data.line(x=[6, 7, 8, 9, 10], y=[10, 40, 20, 30, 50], step=True, label='step')
line_chart.data.line(x=[11, 12, 13, 14, 15], y=[10, 40, 20, 30, 50], spline=True, label='spline')
HTML(line_chart.get_html_string())
Out[5]:
In [6]:
no_marker_line_chart = c3py.Chart('no_marker_line_chart')
no_marker_line_chart.data.line(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='line')
no_marker_line_chart.point.set_visibility(False)
HTML(no_marker_line_chart.get_html_string())
Out[6]:
In [7]:
area_chart = c3py.Chart('area_chart')
area_chart.data.area(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='area')
area_chart.data.area(x=[6, 7, 8, 9, 10], y=[10, 40, 20, 30, 50], step=True, label='area_step')
area_chart.data.area(x=[11, 12, 13, 14, 15], y=[10, 40, 20, 30, 50], spline=True, label='area_spline')
HTML(area_chart.get_html_string())
Out[7]:
In [8]:
stacked_area_chart = c3py.Chart('stacked_area_chart')
stacked_area_chart.data.area(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='area_one')
stacked_area_chart.data.area(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='area_two')
stacked_area_chart.data.area(x=[6, 7, 8, 9, 10], y=[10, 40, 20, 30, 50], label='area_three')
stacked_area_chart.data.group_series(['area_one', 'area_two'])
HTML(stacked_area_chart.get_html_string())
Out[8]:
In [9]:
bar_chart = c3py.Chart('bar_chart')
bar_chart.data.bar(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='bar')
HTML(bar_chart.get_html_string())
Out[9]:
In [10]:
stacked_bar_chart = c3py.Chart('stacked_bar_chart')
stacked_bar_chart.data.bar(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='bar_one')
stacked_bar_chart.data.bar(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='bar_two')
stacked_bar_chart.data.bar(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='bar_three')
stacked_bar_chart.data.group_series(['bar_one', 'bar_two'])
HTML(stacked_bar_chart.get_html_string())
Out[10]:
In [11]:
scatter_chart = c3py.Chart('scatter_chart')
scatter_chart.data.scatter(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='scatter')
HTML(scatter_chart.get_html_string())
Out[11]:
In [12]:
combination_chart = c3py.Chart('combination_chart')
combination_chart.data.line(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='line')
combination_chart.data.area(x=[1, 2, 3, 4, 5], y=[5, 20, 10, 15, 25], label='area')
combination_chart.data.scatter(x=[6, 7, 8, 9, 10], y=[10, 40, 20, 30, 50], label='scatter')
combination_chart.data.bar(x=[6, 7, 8, 9, 10], y=[5, 20, 10, 15, 25], label='bar')
HTML(combination_chart.get_html_string())
Out[12]:
In [13]:
category_axis = c3py.Chart('category_axis')
category_axis.axes.x_axis.set_type('category')
category_axis.data.bar(x=['a', 'b', 'c', 'd', 'e'], y=[10, 40, 20, 30, 50], label='bar_category')
HTML(category_axis.get_html_string())
Out[13]:
In [14]:
timeseries_axis = c3py.Chart('timeseries_axis')
timeseries_axis.axes.x_axis.set_type('timeseries')
timeseries_axis.data.line(x=['2000-01-01', '2000-01-02', '2000-01-03', '2000-01-04', '2000-01-05'], y=[10, 40, 20, 30, 50], label='line_timeseries')
HTML(timeseries_axis.get_html_string())
Out[14]:
In [15]:
axis_range_chart = c3py.Chart('axis_range_chart')
axis_range_chart.data.line(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='line')
axis_range_chart.axes.y_axis.set_range_min(0)
axis_range_chart.axes.y_axis.set_range_max(100)
axis_range_chart.axes.x_axis.set_range(-20, 80)
HTML(axis_range_chart.get_html_string())
Out[15]:
In [16]:
axis_padding_chart = c3py.Chart('axis_padding_chart')
axis_padding_chart.data.line(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='line')
# y axis padding is in pixels
axis_padding_chart.axes.y_axis.padding.set('bottom', 10)
axis_padding_chart.axes.y_axis.padding.set('top', 20)
# x axis padding is in the unit of the x axis
axis_padding_chart.axes.x_axis.padding.set('right', 5)
HTML(axis_padding_chart.get_html_string())
Out[16]:
In [17]:
axis_label_chart = c3py.Chart('axis_label_chart')
axis_label_chart.data.line(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='line')
axis_label_chart.axes.y_axis.label.set('y_label')
axis_label_chart.axes.x_axis.label.set('x_label', label_position='inner-right')
HTML(axis_label_chart.get_html_string())
Out[17]:
In [18]:
axis_height_chart = c3py.Chart('axis_height_chart')
axis_height_chart.data.bar(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='bar')
# x axis height is in pixels
axis_height_chart.axes.x_axis.set_height(120)
HTML(axis_height_chart.get_html_string())
Out[18]:
For formatting of numbers, see https://github.com/mbostock/d3/wiki/Formatting.
For formatting of times, see https://github.com/mbostock/d3/wiki/Time-Formatting.
In [19]:
tick_format_chart = c3py.Chart('tick_format_chart')
tick_format_chart.axes.x_axis.set_type('timeseries')
tick_format_chart.data.line(x=['2000-01-01', '2000-01-02', '2000-01-03', '2000-01-04', '2000-01-05'], y=[10, 40, 20, 30, 50], label='line_timeseries')
tick_format_chart.axes.x_axis.ticks.set_format('%A %d %B %Y')
tick_format_chart.axes.y_axis.ticks.set_format('$,')
HTML(tick_format_chart.get_html_string())
Out[19]:
In [20]:
tick_count_chart = c3py.Chart('tick_count_chart')
tick_count_chart.data.line(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='line')
tick_count_chart.axes.y_axis.ticks.set_count(3)
tick_count_chart.axes.x_axis.ticks.set_count(9)
HTML(tick_count_chart.get_html_string())
Out[20]:
In [21]:
tick_values_chart = c3py.Chart('tick_values_chart')
tick_values_chart.data.line(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='line')
tick_values_chart.axes.y_axis.ticks.set_values([15, 25, 45])
tick_values_chart.axes.x_axis.ticks.set_values([1, 1.5, 2, 4, 5])
HTML(tick_values_chart.get_html_string())
Out[21]:
In [22]:
tick_culling_chart = c3py.Chart('tick_culling_chart')
tick_culling_chart.data.bar(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='line')
tick_culling_chart.axes.x_axis.ticks.cull(max_ticks=3)
HTML(tick_culling_chart.get_html_string())
Out[22]:
In [23]:
tick_multiline_chart = c3py.Chart('tick_multiline_chart')
tick_multiline_chart.axes.x_axis.set_type('category')
tick_multiline_chart.data.bar(x=['longstringsnormallyoccupymultiplelines_' + str(i) for i in range(1, 6)], y=[10, 40, 20, 30, 50], label='bar_category')
tick_multiline_chart.axes.x_axis.ticks.set_multiline(False)
tick_multiline_chart.axes.x_axis.ticks.rotate(90)
HTML(tick_multiline_chart.get_html_string())
Out[23]:
In [24]:
tick_fitting_chart = c3py.Chart('tick_fitting_chart')
tick_fitting_chart.axes.x_axis.set_type('timeseries')
tick_fitting_chart.data.line(x=['2000-01-01', '2000-02-01', '2000-02-02', '2000-02-03', '2000-02-04'], y=[10, 40, 20, 30, 50], label='line_timeseries')
tick_fitting_chart.axes.x_axis.ticks.set_fit(False)
HTML(tick_fitting_chart.get_html_string())
Out[24]:
In [25]:
secondary_axis_chart = c3py.Chart('secondary_axis_chart')
secondary_axis_chart.axes.add_secondary_y()
secondary_axis_chart.data.bar(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='primary_y_axis', axis='y')
secondary_axis_chart.data.line(x=[1, 2, 3, 4, 5], y=[5, 3, 2, 4, 1], label='secondary_y_axis', axis='y2')
secondary_axis_chart.axes.y2_axis.set_range(-10, 10)
secondary_axis_chart.axes.y2_axis.ticks.set_format('.2f')
HTML(secondary_axis_chart.get_html_string())
Out[25]:
In [26]:
grid_visibility_chart = c3py.Chart('grid_visibility_chart')
grid_visibility_chart.data.bar(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='bar')
grid_visibility_chart.grid.show(x=False, y=True)
HTML(grid_visibility_chart.get_html_string())
Out[26]:
In [27]:
grid_line_chart = c3py.Chart('grid_line_chart')
grid_line_chart.data.line(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='line')
grid_line_chart.grid.custom_grid_line(axis='x', value=2.5, label='x_grid_line')
grid_line_chart.grid.custom_grid_line(axis='y', value=15, label='y_grid_line', label_position='start')
HTML(grid_line_chart.get_html_string())
Out[27]:
In [28]:
legend_visibility_chart = c3py.Chart('legend_visibility_chart')
legend_visibility_chart.data.bar(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='bar')
legend_visibility_chart.legend.hide()
HTML(legend_visibility_chart.get_html_string())
Out[28]:
In [29]:
legend_series_visibility_chart = c3py.Chart('legend_series_visibility_chart')
legend_series_visibility_chart.data.bar(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='bar')
legend_series_visibility_chart.data.line(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='line')
legend_series_visibility_chart.legend.hide_series(['line'])
HTML(legend_series_visibility_chart.get_html_string())
Out[29]:
In [30]:
legend_position_chart = c3py.Chart('legend_position_chart')
legend_position_chart.data.bar(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='bar')
legend_position_chart.data.line(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='line')
legend_position_chart.legend.set_position('inset', inset_anchor='top-left')
HTML(legend_position_chart.get_html_string())
Out[30]:
In [31]:
tooltip_visibility_chart = c3py.Chart('tooltip_visibility_chart')
tooltip_visibility_chart.data.line(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='line')
tooltip_visibility_chart.tooltip.hide()
HTML(tooltip_visibility_chart.get_html_string())
Out[31]:
In [32]:
tooltip_grouping_chart = c3py.Chart('tooltip_grouping_chart')
tooltip_grouping_chart.data.line(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='line_one')
tooltip_grouping_chart.data.line(x=[1, 2, 3, 4, 5], y=[5, 20, 10, 15, 25], label='line_two')
tooltip_grouping_chart.tooltip.ungroup()
HTML(tooltip_grouping_chart.get_html_string())
Out[32]:
In [33]:
tooltip_title_chart = c3py.Chart('tooltip_title_chart')
tooltip_title_chart.data.bar(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='bar')
tooltip_title_chart.tooltip.tooltip_format.set_title('"value on x axis = " + x')
HTML(tooltip_title_chart.get_html_string())
Out[33]:
In [34]:
regions_chart = c3py.Chart('regions_chart')
regions_chart.data.line(x=[1, 2, 3, 4, 5], y=[10, 40, 20, 30, 50], label='line')
regions_chart.regions.add(name='x_region', axis='x', start=2, end=4, color='red')
regions_chart.regions.add(name='y_region', axis='y', start=40, end=50, color='green')
HTML(regions_chart.get_html_string())
Out[34]:
In [36]:
%%javascript
$.each($(":header"), function(index, value) {
value.id = value.innerText.replace(/\s+/g, '').toLowerCase();
var heading_level = parseInt(value.localName.charAt(1));
$("#table_of_contents").append(Array((heading_level - 1) * 6).join(" ") + "<a href='#" + value.id + "'>" + value.innerText + "</a><br />");
});