{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import xarray as xr\n", "import netCDF4 as nc\n", "from pathlib import Path\n", "from datetime import datetime as dt\n", "import geoviews as gv\n", "import numpy as np\n", "import param\n", "from holoviews.operation.datashader import datashade\n", "import panel as pn\n", "import holoviews as hv\n", "from holoviews import opts\n", "hv.extension('bokeh')\n", "pn.extension()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "data_dir = Path('../COVID-19/csse_covid_19_data')\n", "time_series_path = data_dir / 'csse_covid_19_time_series' / 'time_series_19-covid-{VAR}.csv'\n", "daily_reports_path = data_dir / 'csse_covid_19_daily_reports' / '{DATE}.csv'\n", "VARS = ['Confirmed', 'Deaths', 'Recovered']\n", "\n", "data_vars = list()\n", "\n", "dims = ['Aggrigation', 'Quantity', 'Region', 'Date']\n", "for var in VARS:\n", " df = pd.read_csv(time_series_path.as_posix().format(VAR=var))\n", " data_vars.append(df.iloc[:,4:].values)\n", "data_vars.append(data_vars[0] - data_vars[1] - data_vars[2]) # active cases\n", "VARS.append('Active')\n", "data_vars = np.stack(data_vars)\n", "data_vars = np.stack((data_vars, np.diff(data_vars, axis=-1, n=1, prepend=0))) # daily changes\n", "data_vars={'counts': (dims, np.stack(data_vars))}\n", "\n", "coords = dict(\n", " Country=('Region', df['Country/Region']),\n", " Province_State=('Region', df['Province/State']),\n", " Date=df.columns.tolist()[4:],\n", " longitude=('Region', df['Long']),\n", " latitude=('Region', df['Lat']),\n", " Quantity=VARS,\n", " Aggrigation=['Totals', 'Daily']\n", ")\n", "data = xr.Dataset(data_vars=data_vars, coords=coords)\n", "data" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "cdata = data.groupby('Country').sum('Region')\n", "ds = hv.Dataset(cdata, kdims=['Country', 'Date', 'Quantity', 'Aggrigation'], \n", " vdims=['counts'])\n", "dates = data['Date'].values.tolist()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dsel = ds.select(Aggrigation='Daily').aggregate(dimensions=['Quantity', 'Date'], function=np.sum)\n", "curves = dsel.to(hv.Curve, 'Date', ).options(tools=['hover'])\n", "curves.overlay(['Quantity']).options(\n", " legend_position='top_left', \n", " width=800,\n", " height=400,\n", " xrotation=60,\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dsel = ds.select(Aggrigation='Totals').aggregate(dimensions=['Quantity', 'Date'], function=np.sum)\n", "curves = dsel.to(hv.Curve, 'Date', ).options(tools=['hover'])\n", "curves.overlay(['Quantity']).options(\n", " legend_position='top_left', \n", " width=800,\n", " height=400,\n", " xrotation=60,\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def curves(countries, quantity):\n", " dsel = ds.select(Country=countries, Quantity=quantity, Aggrigation='Totals')\n", " curves = dsel.to(hv.Curve, 'Date', ).options(tools=['hover'])\n", " return curves.overlay(['Country', 'Quantity']).options(\n", " legend_position='top_left', \n", " width=800,\n", " height=400,\n", " xrotation=60,\n", " )\n", "curves(['US', 'China'], 'Active')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dsel = ds.select(Aggrigation='Daily', Quantity='Active')\n", "dsel = dsel.aggregate(dimensions=['Date'], function=np.sum)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def bars(quantity):\n", " dsel = ds.select(Aggrigation='Daily', Quantity=quantity).aggregate(dimensions=['Date'], function=np.sum)\n", "\n", " bars = hv.Bars(dsel, kdims=['Date'])\n", " return bars.opts(width=800, height=400, stacked=False, show_legend=False, xrotation=60)\n", " \n", "bars('Active')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class CovidStateCurves(param.Parameterized):\n", " states = param.ListSelector(default=['Mississippi', 'Louisiana'], objects=usdata['Province_State'].values)\n", " \n", " \n", " @param.depends('states')\n", " def curves(self):\n", " dsel = ds.select(Province_State=self.states, Quantity='Active')\n", " curves = dsel.to(hv.Curve, 'Date', )\n", "# curves = hv.Curve(dsel, kdims=['Date'])\n", " return curves.overlay(['Province_State', 'Quantity']).opts(\n", " legend_position='top_left', \n", " width=800,\n", " height=400,\n", " xrotation=60 )\n", " \n", " @param.depends('states')\n", " def bars(self):\n", " dsel = ds.select(Province_State=self.states, Date=data['Date'][-1])\n", "\n", " bars = hv.Bars(dsel, kdims=['Province_State', 'Quantity'])\n", " return bars.opts(width=800, height=400, stacked=False, show_legend=False, xrotation=60)\n", " \n", " def panel(self):\n", " return pn.Row(\n", " pn.Param(self.param.states, widgets={'states': {'height': 800}}),\n", " pn.Column(\n", " self.curves,\n", " self.bars,\n", " \n", " ),\n", " )\n", "\n", "ccc = CovidStateCurves()\n", "ccc.panel()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dsel = ds.select(Country=ccc.countries, Date='3/15/20')\n", "\n", "# bars = dsel.to(hv.Bars, kdims=['Country', 'Date'])\n", "bars = hv.Bars(dsel, kdims=['Country', 'Quantity'])\n", "bars.opts(width=800, height=400, stacked=False, show_legend=False, xrotation=60)\n", "ccc.bars()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "tiles = gv.tile_sources.CartoDark\n", "dates = data['Date'].values.tolist()\n", "class CovidViewer(param.Parameterized):\n", " date = param.ObjectSelector(default=dates[1], objects=dates)\n", " variable = param.ObjectSelector(default='Confirmed', objects=VARS)\n", " \n", " @param.depends('date', 'variable')\n", " def infection_map(self):\n", " seldata = {\n", " 'longitude': data['longitude'], \n", " 'latitude': data['latitude'], \n", " 'Confirmed': data.sel(Quantity='Confirmed', Date=self.date)['counts'],\n", " 'Deaths': data.sel(Quantity='Deaths', Date=self.date)['counts'],\n", " 'Recovered': data.sel(Quantity='Recovered', Date=self.date)['counts'],\n", " 'Active': data.sel(Quantity='Active', Date=self.date)['counts'],\n", " 'Country': data['Country'],\n", " 'State/Province': data['Province_State'],\n", " }\n", "# gvdata = gv.Dataset(seldata, kdims=['latitude', 'longitude'], vdims=['Variable'])\n", "# heatmap = gvdata.to(hv.HeatMap)\n", "\n", " # points = gvdata.to(gv.Points, ['Lat', 'Lon'])\n", " points = gv.Points(seldata, kdims=['longitude', 'latitude'], vdims=VARS+['Country', 'State/Province'])\n", " return tiles * points.opts(\n", " size=gv.dim(self.variable).log()*4,\n", " logz=True,\n", " fill_color=self.variable,\n", " fill_alpha=.5,\n", " line_color='gray', \n", " cmap='hot',\n", " width=800, height=600, global_extent=True, tools=['hover'], show_legend=False)\n", " \n", " @param.depends('date')\n", " def date_label(self):\n", " return f'## {self.date}'\n", " \n", " def panel(self):\n", " player = pn.widgets.Player(name='Player', start=0, end=100, value=32, loop_policy='loop')\n", " return pn.Column(\n", " self.param.variable,\n", " pn.Param(self.param.date, widgets={'date': pn.widgets.DiscretePlayer}),\n", " self.date_label,\n", " self.infection_map)\n", "\n", "# hv.DynamicMap(infection_map, kdims=['date', 'variable']\n", "# ).redim.values(variable=VARS, date=data['Date'].values)\n", "\n", "cv = CovidViewer()\n", "cv.panel()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "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.6.10" } }, "nbformat": 4, "nbformat_minor": 4 }