✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🧬 Learn how to build RNA-Seq data apps with Python & Dash. Register for the May 20 Webinar!

Show and Tell - FIFA World Cup 2018 Match Explorer

Hi! I’ve opened this thread to share an application made using Dash.

Description: The FIFA WC 2018 Match Explorer enables users to select any of the 64 world cup matches and see multiple interactive visualizations about in-game events, tactics and player performances.

Hosted at: http://www.datadabble.in
Github repo: https://github.com/hkhare42/wc-explorer-dash
Blog post with more info: https://datadabble.blogspot.com/2018/11/fifa-world-cup-2018-match-explorer.html




  • App designed for big screens. Use Chrome/Firefox and full screen mode for best experience.

  • Click on the ‘Information Bar’ at the top of the screen to access match selection dropdown and theme switching option.

  • Interactivity:

    All plots have hover labels/features

    xG plot has click and drag feature to select a time range. Double click on same/reset view to zoom out.

    Passing network map has click feature to select a specific player.

    Use click and drag to zoom into plots. Double click/click on reset view button to reset view.


:heart_eyes: So nice! The bouncing ball loading screen made my day :smiley_cat: I also love the cross-linking player profiles, very well thought out :100:

Thanks for sharing!

For other readers, here are some screenshots of the app:


Hey @chriddyp Thanks a lot for your praise. Hearing it from you made my day! I shared this app on reddit and one of the feedback I got was about slow loading times.

Now this is the first time I’m hosting a server and I’ve followed Dash’s deployment guide to set up a EC2(Ubuntu)-Nginx-Gunicorn based solution. Are there any resources I could refer to learn more about optimizing load times? If you could suggest something/direct me to a guide/tutorial, that would be great!

Thanks again!

1 Like

It fully loaded in about 5 seconds which is not that bad considering you have 38 callbacks firing up on page load. Some of those callbacks takes longer to complete, you can see them in the network tab of the chrome developer tool. To identify the callback you can look at the request payload:

Of course if the EC2 instance is in America and you access it from Europe there will be more latency. You would need set up instances in other regions and use a DNS (route53) to send the traffic to the right place.

1 Like

Thanks for referring to using Chrome’s developer tool network tab to look into this, that was quite helpful to me!
Could you and @hkhare clarify something about deploying to an EC2 instance?
If i recall correctly the dash deployment guide only described deploying to Heroku and only using gunicorn + a procfile, rather than nginx+gunicorn and a .wsgi file.

Yeah @adi my bad. I confused the guide I used with the Dash deployment guide. What I essentially picked up from the Dash deployment guide was that by exposing the server, I could then deploy my Dash app like any Flask app. Then I moved to this Digital Ocean Guide and followed it religiously: https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-gunicorn-and-nginx-on-ubuntu-16-04

1 Like

A trick I do is to make sure my layout contains all the initial required information and then raise PreventUpdate on page load for all the callbacks.

To figure out if it’s currently the page load I will include a dcc.Location component in the state and detect if it’s attribute pathname is None.

It’s all a little hacky, but I don’t know any better way to reduce the callbacks performance penalty on pageload. I have an application that has >300 callbacks, and the only performance issue is they are all forced to run on page load.

We are planning to remove the None callbacks for the 1.0.0 release of dash.

1 Like

To be clear, you’re removing the fact that the property is None or that the callback fires on page load?

If it’s the first I’m sure I can come up with some other hacky workaround for firing raise PreventUpdateon page-load.

If it’s the second that would be massive! It would be allow apps to be way more scalable :grinning:. I’ve seen discussion on this before that the architecture would make it very difficult, but the only pros I’ve seen are that it would remove a developer nuisance, not that some apps are basically impossible to write because page-load is proportional to number of callbacks.

We’re filtering the nil values from the initial callback layout collection, you will only get the initial callback if the prop is set by the layout. You will still be able populate fields by initial callback if you have an Input with id as prop ie: @app.callback(Output('my-div', 'children'), [Input('my-div', 'id')]).

1 Like

Hey Philippe, thanks for pointing me in the right direction. I read up on developer tools and domain name systems, and learnt a lot.

Also, I figured that since the overall data I’m using right now is not that big, it would be a much better idea for me to use global variables to store the entire data along with a chunk of aggregates, and simply deliver them on callback requests. I know one has to be wary with using global variables but since I’m not modifying any, I think it should be fine.

The site now loads up in significantly less time and even all the interactions are much smoother. Check it out: http://www.datadabble.in


Wow, pretty impressive speed increase.