Bokeh vs Dash — Which is the Best Dashboard Framework for Python?

In this article, we’ll compare Bokeh and Dash (by Plotly), two Python alternatives for the Shiny framework for R, using the same example.

Bokeh and Dash: an overview

Bokeh has been around since 2013. Dash has been announced recently and it was featured in our Best of AI series. Dash’s number of stars on Github is growing exponentially and may exceed Bokeh’s.

You can see an updated version of this graph here

Maintained by?

License:

  • Bokeh: BSD 3-Clause (permissive license). It depends on Jinja2 (BSD), MarkupSafe (BSD), PyYAML (MIT), numpy (BSD), python-dateutil (simplified BSD), and Tornado (Apache). All these licenses are permissive as well.
  • Dash: MIT (permissive license). It depends on Flask (BSD), MarkupSafe (BSD), chardet (LGPL), decorator (new BSD license), jsonschema (MIT), plotly (MIT), pytz (MIT), requests (Apache 2.0), traitlets (BSD), urllib3 (MIT). All these licenses are permissive as well.

Underlying frameworks?

Jupyter and Zeppelin notebooks?

  • Bokeh: supported natively with interactions
  • Dash: not supported, but Plotly is

Requires only Python knowledge?

  • Bokeh: Mostly (some graph interactions must be written in javascript)
  • Dash: Yes for the core framework. You can also write custom React components or find some on the internet.

Comparing the frameworks visually

Bokeh example (left) and Dash example (right)

You can play with the frameworks yourself:

These examples show how a selection component can update the graphs. They also show how selecting data on a graph updated the other components. It is clear on those recordings that Dash is less slowed down by big datasets than Bokeh. Both dashboards also look very similar.

Another point is interaction consistency. See what happens in the Bokeh example when you first select a category on top, then select data on the scatter plot and then unselect a category. Data in the Bokeh graphs becomes inconsistent. If you come up with an elegant solution to this issue, please let me know. On the contrary, Dash will maintain a common state and I’ve never seen inconsistencies arise.

User testimonials (from Reddit)

I gave up on Bokeh a long time ago and have been very happy with plotly and dash. At the time Bokeh was just too hard to use and the documentation wasn’t very good. Plotly has always been incredibly intuitive.
broken_symlink
I personally have been using bokeh and have liked it so far. I recall toying with plotly for some small thing that didn’t work at the time due to a known bug but haven’t had the time to revisit it.
 — Raindash
I’ve been using Dash for a few months and find it great to quickly get something up and running. Incredibly easy to get live updates and great visualisation. Bokeh was just frustrating when I tried it.
MalakElohim
Having used both (started with Bokeh, then moved to Dash), I am finding Dash to be far easier to learn and get working, as well as easier to maintain.
Right now I think that the may detriment to Dash is a lack of some features/capabilities, but it is under pretty active development and new capabilities are coming down the pipe quickly.
Omega037

A quick word about the implementation examples

Before looking at the code comparison between Bokeh and Dash, you should look at this paragraph.

The dataset we’ll base our implementation examples on is a list of Kickstarter projects. I parsed, cleaned and assembled this dataset in a single CSV file that you can find here. How I did it is beyond this article’s scope but feel free to ask me.

The examples are written in Python3. If you need Python go to the Python official website to install it. I also encourage you to set up a virtualenv and install pip.

You will find the examples for Bokeh and Dash in the GitHub repository dashboards-frameworks-comparison. For each dashboard framework, you will find the library dependencies in a file requirements.txt. To install them use pip install -r requirements.txt .

The dataset will be loaded in the following way throughout the examples:

Data loading step used in the dashboard frameworks’ code snippets. It parses a broader category from the initial numerous categories in the dataset and parses the created_at string as a DateTime. We’ll also use a sample of 10000 rows of the dataset for performance purposes.

We’ll also need some global variables for formatting (Note: usage of global variables in a production environment is not advised. It makes the code simpler here).

When giving lines of code for each example, those previous lines will be excluded.


Bokeh implementation example

  • Lines of code for the example: 139
  • Version of Bokeh in the example: 0.12.13
  • Development difficulty felt: 4/5. I found it hard to use the Bokeh data sources because I wanted (and failed) to link them to my pandas dataframes. Configuring graphs to look like I wanted was a hassle, and it took me a lot of time to get around how interactions work.

You can find the whole example in the dashboard-frameworks-comparison repository.

Imports and setup

Import the events, layout helpers, a model that will hold data, models that are configuration tools for plots, two HTML widgets wrapped in Python, and plotting helpers.

For a list of HTML widgets you can use, follow this link.

Interactions

In Bokeh, you need to perform an update of the data sources used by the plots. These updates functions will be triggered by events defined in the layout part. Contrary to Dash, it is not easy to update the graphs with new values when you have more than one input. See for example the complexity of update_num_categories_source

You can find more on interactions in Bokeh here. Bokeh has a wider range of interactions than Dash. For example, you can pan multiple graphs at the same time, which is not possible in Dash right now. I think it’s because Dash aims at being python-only and you need javascript interactions to synchronize pans.

Data sources

Bokeh forces you to use its own data model. They can take pandas dataframes as an input but this leads to limitations. For example I was unable to use the direct mapping of a dataframe to a ColumnDataSource for the two examples above.

Layout

This last bit creates the graphs, attaches them the data sources and defines a layout for those graphs. It seems from its documentation and examples that Bokeh promotes the use of global variables for the figures. I’m not comfortable with it but used if here nevertheless.

Start the Bokeh dashboard

Run bokeh serve app.py

Dash implementation example

  • Lines of code for the example: 105
  • Version of Dash in the example: 0.18.3
  • Development difficulty felt: 2/5. The only difficulty I had was how to use the dcc.Graph object with the regular plotly library. When that was clear for me, development was a breeze.

Imports and setup

Import the framework using the libraries dash, dash_core_components (components that are interactive between one another), dash_html_components (just html code wrapped in Python) and plotly. The app variable is an instance of Flask, so you can use it like any Flask app.

Layout

The layout for the application: one title, one dropdown, and two graphs. Note that because both graphs are interactive, dcc.Graph does not contain the two attributes data and layout. Those attributes are defined in the callbacks functions below.

Interactions

The Dash framework relies on callbacks for interactions. Those callbacks output a dictionary with attributes data and layout. Both are Plotly native objects, so passing from a plotly graph to a Dash dashboard is very quick. The bar chart can be changed either by selecting a category in the dropdown or selecting points in the scatter plot (relayout_data).

Find more about interactions in Dash here.

Start the Dash dashboard

The dashboard runs like a standard Flask application

Run the dashboard with python app.py

Alternatives to Bokeh and Dash

This article was supposed to be a comparison of multiple dashboard frameworks for python. I previously included Pyxley, and Pydashie. However, these projects have either been abandoned or lack proper documentation.

I also had unsuccessfully tested the Bowtie library. The Bowtie author saw this article and made an effort to improve the documentation and include an example based on the Kickstarter Dashboard. I suggest you check it out.

Conclusion

I would use Dash by default:

  • it uses plotly for python which makes it very powerful
  • it uses React on the frontend which makes it easy add components
  • I coded more easily on Dash than on Bokeh, which confirms the opinion of other users I cited

If you’re still unsure about which one to choose:

  • Do a POC on Dash of your most critical features
  • Do a POC on Bokeh if you got blocked by a lack of interactions between graphs (like panning multiple graphs at the same time)
  • Then decide if you want to sacrifice some features to use Dash or if you’re fine with Bokeh

Want more articles like this one? Don’t forget to click the Follow button!


By the way, don’t forget to check out our comparison of the best javascript chart libraries: