Last active
March 19, 2020 22:06
-
-
Save deeplook/d4361f8275f8649a951687327505f8bf to your computer and use it in GitHub Desktop.
COVID-19 dynamics plot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "# COVID-19 Dynamics\n", | |
| "\n", | |
| "There are many visiualizations of the ongoing [COVID-19](https://en.wikipedia.org/wiki/Coronavirus_disease_2019) (or Corona) virus outbreak. As most are static, this one specifically aims to illustrate the dynamics of the COVID-19 virus infection using the official datasets available at https://github.com/CSSEGISandData/COVID-19. It builds on [Jupyter](https://jupyter.org) and [IPyLeaflet](https://github.com/jupyter-widgets/ipyleaflet) (and [Voilà](https://github.com/voila-dashboards/voila) and [MyBinder](https://mybinder.org), soon)." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "from functools import partial\n", | |
| "from math import pi\n", | |
| "\n", | |
| "from ipyleaflet import basemap_to_tiles, basemaps, CircleMarker, \\\n", | |
| " FullScreenControl, LayersControl, LayerGroup, Map, Marker, \\\n", | |
| " WidgetControl\n", | |
| "from ipywidgets import IntSlider, HBox, jslink, Layout, Output, Play\n", | |
| "import pandas as pd" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "url = (\"https://raw.githubusercontent.com/CSSEGISandData/COVID-19/\"\n", | |
| " \"master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Confirmed.csv\")\n", | |
| "df_confirmed = pd.read_csv(url)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "# df_confirmed.describe()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "# df_confirmed.head()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "day_cols = [col for col in df_confirmed.columns if col.count(\"/\") == 2]\n", | |
| "locations = list(zip(df_confirmed.Lat, df_confirmed.Long))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "def radius_sphere(volume):\n", | |
| " return (volume / pi / 4 * 3) ** (1/2.75)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "def slider_changed(change, the_map=None, output=None, slider=None, group=None):\n", | |
| " day = change['new']\n", | |
| " values = df_confirmed[day_cols[day]]\n", | |
| " if slider:\n", | |
| " slider.description = day_cols[day]\n", | |
| " if the_map:\n", | |
| " circle_layers = list(l for l in group.layers if type(l) == CircleMarker)\n", | |
| " if not circle_layers:\n", | |
| " # if output:\n", | |
| " # with output:\n", | |
| " # print(f\"updating {day_cols[day]}\")\n", | |
| " markers = []\n", | |
| " for i, loc in enumerate(locations):\n", | |
| " rad = int(radius_sphere(values[i]))\n", | |
| " marker = CircleMarker(\n", | |
| " location=tuple(loc),\n", | |
| " radius=rad,\n", | |
| " color=\"red\" if rad > 0 else \"white\",\n", | |
| " opacity=rad > 0)\n", | |
| " markers.append(marker)\n", | |
| " group.layers = tuple(markers)\n", | |
| " else:\n", | |
| " for i, lay in enumerate(circle_layers):\n", | |
| " rad = int(radius_sphere(values[i]))\n", | |
| " lay.radius = rad\n", | |
| " lay.color=\"red\" if rad > 0 else \"white\"\n", | |
| " lay.opacity = rad > 0" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "# output = Output()\n", | |
| "# display(output)\n", | |
| "\n", | |
| "m = Map(zoom=2, basemap=basemaps.CartoDB.Positron)\n", | |
| "\n", | |
| "m += FullScreenControl()\n", | |
| "\n", | |
| "# dark_matter_layer = basemap_to_tiles(basemaps.CartoDB.DarkMatter)\n", | |
| "# m.add_layer(dark_matter_layer)\n", | |
| "# nat_geo_world_layer = basemap_to_tiles(basemaps.Esri.NatGeoWorldMap)\n", | |
| "# m.add_layer(nat_geo_world_layer)\n", | |
| "layers_control = LayersControl(position='topright')\n", | |
| "m += layers_control\n", | |
| "\n", | |
| "confirmed_group = LayerGroup(layers=[], name=\"Confirmed\")\n", | |
| "m += confirmed_group\n", | |
| "\n", | |
| "play = Play(\n", | |
| " value=0,\n", | |
| " min=0,\n", | |
| " max=len(day_cols)-1,\n", | |
| " step=1,\n", | |
| " interval=500,\n", | |
| " # description=\"Press play\",\n", | |
| " disabled=False\n", | |
| ")\n", | |
| "day_slider = IntSlider(\n", | |
| " description='Day:',\n", | |
| " layout=Layout(width=\"600px\"),\n", | |
| " min=-1, max=len(day_cols)-1, value=-1)\n", | |
| "jslink((play, 'value'), (day_slider, 'value'))\n", | |
| "cb = partial(slider_changed,\n", | |
| " the_map=m,\n", | |
| " # output=output,\n", | |
| " group=confirmed_group,\n", | |
| " slider=day_slider)\n", | |
| "day_slider.observe(cb, names='value')\n", | |
| "widget_control1 = WidgetControl(\n", | |
| " widget=HBox([play, day_slider]),\n", | |
| " position='bottomleft',\n", | |
| " layout=Layout(width=\"600px\"),\n", | |
| ")\n", | |
| "day_slider.value = 0\n", | |
| "day_slider.min = 0\n", | |
| "m.add_control(widget_control1)\n", | |
| "\n", | |
| "m" | |
| ] | |
| } | |
| ], | |
| "metadata": { | |
| "kernelspec": { | |
| "display_name": "Python 3", | |
| "language": "python", | |
| "name": "python3" | |
| }, | |
| "language_info": { | |
| "codemirror_mode": { | |
| "name": "ipython", | |
| "version": 3 | |
| }, | |
| "file_extension": ".py", | |
| "mimetype": "text/x-python", | |
| "name": "python", | |
| "nbconvert_exporter": "python", | |
| "pygments_lexer": "ipython3", | |
| "version": "3.7.6" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 4 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment