Skip to content
Snippets Groups Projects
covidtracking-example.ipynb 53.5 KiB
Newer Older
   "source": [
    "import pandas as pd\n",
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Look at the metadata"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "metadata_df = pd.read_json('../../data/covidtracking/states-metadata.json')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>state</th>\n",
       "      <th>covid19SiteOld</th>\n",
       "      <th>covid19SiteSecondary</th>\n",
       "      <th>twitter</th>\n",
       "      <th>pui</th>\n",
       "      <th>pum</th>\n",
       "      <th>notes</th>\n",
       "      <th>name</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>AK</td>\n",
       "      <td>http://dhss.alaska.gov/dph/Epi/id/Pages/COVID-...</td>\n",
       "      <td>http://dhss.alaska.gov/dph/Epi/id/Pages/COVID-...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>@Alaska_DHSS</td>\n",
       "      <td>All data</td>\n",
       "      <td>False</td>\n",
       "      <td>Unclear if their reported number means \"person...</td>\n",
       "      <td>Alaska</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>AL</td>\n",
       "      <td>http://www.alabamapublichealth.gov/infectiousd...</td>\n",
       "      <td>https://alpublichealth.maps.arcgis.com/apps/op...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>@alpublichealth</td>\n",
       "      <td>No data</td>\n",
       "      <td>False</td>\n",
       "      <td>Last negative count from 3/16.</td>\n",
       "      <td>Alabama</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>AR</td>\n",
       "      <td>https://www.healthy.arkansas.gov/programs-serv...</td>\n",
       "      <td>https://www.healthy.arkansas.gov/programs-serv...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>@adhpio</td>\n",
       "      <td>All data</td>\n",
       "      <td>True</td>\n",
       "      <td>Pending = \"PUIs\"</td>\n",
       "      <td>Arkansas</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>AZ</td>\n",
       "      <td>https://www.azdhs.gov/preparedness/epidemiolog...</td>\n",
       "      <td>https://www.azdhs.gov/preparedness/epidemiolog...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>@azdhs</td>\n",
       "      <td>All data</td>\n",
       "      <td>False</td>\n",
       "      <td>Negative = “Ruled Out”. Our total is slightly ...</td>\n",
       "      <td>Arizona</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>CA</td>\n",
       "      <td>https://www.cdph.ca.gov/Programs/CID/DCDC/Page...</td>\n",
       "      <td>https://www.latimes.com/projects/california-co...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>@CAPublicHealth</td>\n",
       "      <td>Only positives</td>\n",
       "      <td>False</td>\n",
       "      <td>Only positives reported regularly. Add deaths ...</td>\n",
       "      <td>California</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  state                                     covid19SiteOld  \\\n",
       "0    AK  http://dhss.alaska.gov/dph/Epi/id/Pages/COVID-...   \n",
       "1    AL  http://www.alabamapublichealth.gov/infectiousd...   \n",
       "2    AR  https://www.healthy.arkansas.gov/programs-serv...   \n",
       "3    AZ  https://www.azdhs.gov/preparedness/epidemiolog...   \n",
       "4    CA  https://www.cdph.ca.gov/Programs/CID/DCDC/Page...   \n",
       "\n",
       "                                         covid19Site  covid19SiteSecondary  \\\n",
       "0  http://dhss.alaska.gov/dph/Epi/id/Pages/COVID-...                   NaN   \n",
       "1  https://alpublichealth.maps.arcgis.com/apps/op...                   NaN   \n",
       "2  https://www.healthy.arkansas.gov/programs-serv...                   NaN   \n",
       "3  https://www.azdhs.gov/preparedness/epidemiolog...                   NaN   \n",
       "4  https://www.latimes.com/projects/california-co...                   NaN   \n",
       "           twitter             pui    pum  \\\n",
       "0     @Alaska_DHSS        All data  False   \n",
       "1  @alpublichealth         No data  False   \n",
       "2          @adhpio        All data   True   \n",
       "3           @azdhs        All data  False   \n",
       "4  @CAPublicHealth  Only positives  False   \n",
       "                                               notes        name  \n",
       "0  Unclear if their reported number means \"person...      Alaska  \n",
       "1                     Last negative count from 3/16.     Alabama  \n",
       "2                                   Pending = \"PUIs\"    Arkansas  \n",
       "3  Negative = “Ruled Out”. Our total is slightly ...     Arizona  \n",
       "4  Only positives reported regularly. Add deaths ...  California  "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "metadata_df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Look at the data"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "outputs": [],
   "source": [
    "data_df = pd.read_json('../../data/covidtracking/states-daily.json')\n",
    "data_df['date'] = pd.to_datetime(data_df['date'], format=\"%Y%m%d\")"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>state</th>\n",
       "      <th>positive</th>\n",
       "      <th>negative</th>\n",
       "      <th>pending</th>\n",
       "      <th>death</th>\n",
       "      <th>total</th>\n",
       "      <th>dateChecked</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2020-03-19</td>\n",
       "      <td>6</td>\n",
       "      <td>400.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>406</td>\n",
       "      <td>2020-03-19T20:00:00Z</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2020-03-19</td>\n",
       "      <td>68</td>\n",
       "      <td>28.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "      <td>96</td>\n",
       "      <td>2020-03-19T20:00:00Z</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2020-03-19</td>\n",
       "      <td>46</td>\n",
       "      <td>310.0</td>\n",
       "      <td>113.0</td>\n",
       "      <td>469</td>\n",
       "      <td>2020-03-19T20:00:00Z</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2020-03-19</td>\n",
       "      <td>AS</td>\n",
       "      <td>0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0</td>\n",
       "      <td>2020-03-19T20:00:00Z</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2020-03-19</td>\n",
       "      <td>AZ</td>\n",
       "      <td>44</td>\n",
       "      <td>175.0</td>\n",
       "      <td>130.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>349</td>\n",
       "      <td>2020-03-19T20:00:00Z</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        date state  positive  negative  pending  death  total  \\\n",
       "0 2020-03-19    AK         6     400.0      NaN    NaN    406   \n",
       "1 2020-03-19    AL        68      28.0      NaN    0.0     96   \n",
       "2 2020-03-19    AR        46     310.0    113.0    NaN    469   \n",
       "3 2020-03-19    AS         0       NaN      NaN    0.0      0   \n",
       "4 2020-03-19    AZ        44     175.0    130.0    0.0    349   \n",
       "0  2020-03-19T20:00:00Z  \n",
       "1  2020-03-19T20:00:00Z  \n",
       "2  2020-03-19T20:00:00Z  \n",
       "3  2020-03-19T20:00:00Z  \n",
       "4  2020-03-19T20:00:00Z  "
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data_df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Daily counts and totals"
   "metadata": {},
   "outputs": [],
   "source": [
    "# compute daily differences\n",
    "tdf = data_df.sort_values(['state', 'date'], ascending=[True, False]).set_index(['state', 'date'])\n",
    "diffs_df = tdf[['positive', 'negative', 'death']].groupby(level='state').diff(periods=-1).dropna(how='all')\n",
    "tdf_diff=tdf.join(diffs_df, rsuffix='_diff').reset_index()\n",
    "\n",
    "# \"Normalizing\" the totals\n",
    "tdf_diff['total_10'] = tdf_diff['total']/10."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div id=\"altair-viz-65df72664b9f476eaf839e817659dd24\"></div>\n",
       "<script type=\"text/javascript\">\n",
       "  (function(spec, embedOpt){\n",
       "    const outputDiv = document.getElementById(\"altair-viz-65df72664b9f476eaf839e817659dd24\");\n",
       "    const paths = {\n",
       "      \"vega\": \"https://cdn.jsdelivr.net/npm//vega@5?noext\",\n",
       "      \"vega-lib\": \"https://cdn.jsdelivr.net/npm//vega-lib?noext\",\n",
       "      \"vega-lite\": \"https://cdn.jsdelivr.net/npm//vega-lite@4.0.2?noext\",\n",
       "      \"vega-embed\": \"https://cdn.jsdelivr.net/npm//vega-embed@6?noext\",\n",
       "    };\n",
       "\n",
       "    function loadScript(lib) {\n",
       "      return new Promise(function(resolve, reject) {\n",
       "        var s = document.createElement('script');\n",
       "        s.src = paths[lib];\n",
       "        s.async = true;\n",
       "        s.onload = () => resolve(paths[lib]);\n",
       "        s.onerror = () => reject(`Error loading script: ${paths[lib]}`);\n",
       "        document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
       "      });\n",
       "    function showError(err) {\n",
       "      outputDiv.innerHTML = `<div class=\"error\" style=\"color:red;\">${err}</div>`;\n",
       "      throw err;\n",
       "    function displayChart(vegaEmbed) {\n",
       "      vegaEmbed(outputDiv, spec, embedOpt)\n",
       "        .catch(err => showError(`Javascript Error: ${err.message}<br>This usually means there's a typo in your chart specification. See the javascript console for the full traceback.`));\n",
       "\n",
       "    if(typeof define === \"function\" && define.amd) {\n",
       "      requirejs.config({paths});\n",
       "      require([\"vega-embed\"], displayChart, err => showError(`Error loading script: ${err.message}`));\n",
       "    } else if (typeof vegaEmbed === \"function\") {\n",
       "      displayChart(vegaEmbed);\n",
       "    } else {\n",
       "      loadScript(\"vega\")\n",
       "        .then(() => loadScript(\"vega-lite\"))\n",
       "        .then(() => loadScript(\"vega-embed\"))\n",
       "        .catch(showError)\n",
       "        .then(() => displayChart(vegaEmbed));\n",
       "    }\n",
       "  })({\"config\": {\"view\": {\"continuousWidth\": 400, \"continuousHeight\": 300}}, \"hconcat\": [{\"layer\": [{\"mark\": {\"type\": \"bar\", \"size\": 10}, \"encoding\": {\"x\": {\"type\": \"temporal\", \"axis\": {\"title\": \"Date\"}, \"field\": \"date\"}, \"y\": {\"type\": \"quantitative\", \"axis\": {\"title\": \"Daily positive\"}, \"field\": \"daily_positive\"}}, \"height\": 150, \"title\": \"WA\", \"width\": 250}, {\"layer\": [{\"mark\": {\"type\": \"line\", \"color\": \"red\"}, \"encoding\": {\"x\": {\"type\": \"temporal\", \"axis\": {\"title\": \"Date\"}, \"field\": \"date\"}, \"y\": {\"type\": \"quantitative\", \"axis\": {\"title\": \"Total/10\"}, \"field\": \"total_10\"}}, \"height\": 150, \"title\": \"WA\", \"width\": 250}, {\"mark\": {\"type\": \"line\", \"color\": \"orange\"}, \"encoding\": {\"x\": {\"type\": \"temporal\", \"axis\": {\"title\": \"Date\"}, \"field\": \"date\"}, \"y\": {\"type\": \"quantitative\", \"axis\": {\"title\": \"Positive\"}, \"field\": \"positive\"}}, \"height\": 150, \"title\": \"WA\", \"width\": 250}]}], \"data\": {\"name\": \"data-e3884ceed25bdc83e388c03b5394d76a\"}, \"resolve\": {\"scale\": {\"y\": \"independent\"}}}, {\"layer\": [{\"mark\": {\"type\": \"bar\", \"size\": 10}, \"encoding\": {\"x\": {\"type\": \"temporal\", \"axis\": {\"title\": \"Date\"}, \"field\": \"date\"}, \"y\": {\"type\": \"quantitative\", \"axis\": {\"title\": \"Daily positive\"}, \"field\": \"daily_positive\"}}, \"height\": 150, \"title\": \"CA\", \"width\": 250}, {\"layer\": [{\"mark\": {\"type\": \"line\", \"color\": \"red\"}, \"encoding\": {\"x\": {\"type\": \"temporal\", \"axis\": {\"title\": \"Date\"}, \"field\": \"date\"}, \"y\": {\"type\": \"quantitative\", \"axis\": {\"title\": \"Total/10\"}, \"field\": \"total_10\"}}, \"height\": 150, \"title\": \"CA\", \"width\": 250}, {\"mark\": {\"type\": \"line\", \"color\": \"orange\"}, \"encoding\": {\"x\": {\"type\": \"temporal\", \"axis\": {\"title\": \"Date\"}, \"field\": \"date\"}, \"y\": {\"type\": \"quantitative\", \"axis\": {\"title\": \"Positive\"}, \"field\": \"positive\"}}, \"height\": 150, \"title\": \"CA\", \"width\": 250}]}], \"data\": {\"name\": \"data-5524f3d9a011a4455f9aef2d5f2b332f\"}, \"resolve\": {\"scale\": {\"y\": \"independent\"}}}, {\"layer\": [{\"mark\": {\"type\": \"bar\", \"size\": 10}, \"encoding\": {\"x\": {\"type\": \"temporal\", \"axis\": {\"title\": \"Date\"}, \"field\": \"date\"}, \"y\": {\"type\": \"quantitative\", \"axis\": {\"title\": \"Daily positive\"}, \"field\": \"daily_positive\"}}, \"height\": 150, \"title\": \"NY\", \"width\": 250}, {\"layer\": [{\"mark\": {\"type\": \"line\", \"color\": \"red\"}, \"encoding\": {\"x\": {\"type\": \"temporal\", \"axis\": {\"title\": \"Date\"}, \"field\": \"date\"}, \"y\": {\"type\": \"quantitative\", \"axis\": {\"title\": \"Total/10\"}, \"field\": \"total_10\"}}, \"height\": 150, \"title\": \"NY\", \"width\": 250}, {\"mark\": {\"type\": \"line\", \"color\": \"orange\"}, \"encoding\": {\"x\": {\"type\": \"temporal\", \"axis\": {\"title\": \"Date\"}, \"field\": \"date\"}, \"y\": {\"type\": \"quantitative\", \"axis\": {\"title\": \"Positive\"}, \"field\": \"positive\"}}, \"height\": 150, \"title\": \"NY\", \"width\": 250}]}], \"data\": {\"name\": \"data-294eebc48941097d786524a29c373ee4\"}, \"resolve\": {\"scale\": {\"y\": \"independent\"}}}], \"$schema\": \"https://vega.github.io/schema/vega-lite/v4.0.2.json\", \"datasets\": {\"data-e3884ceed25bdc83e388c03b5394d76a\": [{\"state\": \"WA\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 1187, \"negative\": 15918.0, \"pending\": null, \"death\": 66.0, \"total\": 17105, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"positive_diff\": 175.0, \"negative_diff\": 2801.0, \"death_diff\": 14.0, \"total_10\": 1710.5, \"daily_positive\": 175.0}, {\"state\": \"WA\", \"date\": \"2020-03-18T00:00:00\", \"positive\": 1012, \"negative\": 13117.0, \"pending\": null, \"death\": 52.0, \"total\": 14129, \"dateChecked\": \"2020-03-18T20:00:00Z\", \"positive_diff\": 108.0, \"negative_diff\": 1535.0, \"death_diff\": 4.0, \"total_10\": 1412.9, \"daily_positive\": 108.0}, {\"state\": \"WA\", \"date\": \"2020-03-17T00:00:00\", \"positive\": 904, \"negative\": 11582.0, \"pending\": null, \"death\": 48.0, \"total\": 12486, \"dateChecked\": \"2020-03-17T20:00:00Z\", \"positive_diff\": 135.0, \"negative_diff\": 2131.0, \"death_diff\": 6.0, \"total_10\": 1248.6, \"daily_positive\": 135.0}, {\"state\": \"WA\", \"date\": \"2020-03-16T00:00:00\", \"positive\": 769, \"negative\": 9451.0, \"pending\": null, \"death\": 42.0, \"total\": 10220, \"dateChecked\": \"2020-03-16T20:00:00Z\", \"positive_diff\": 127.0, \"negative_diff\": 2329.0, \"death_diff\": 2.0, \"total_10\": 1022.0, \"daily_positive\": 127.0}, {\"state\": \"WA\", \"date\": \"2020-03-15T00:00:00\", \"positive\": 642, \"negative\": 7122.0, \"pending\": null, \"death\": 40.0, \"total\": 7764, \"dateChecked\": \"2020-03-15T20:00:00Z\", \"positive_diff\": 74.0, \"negative_diff\": 1121.0, \"death_diff\": 3.0, \"total_10\": 776.4, \"daily_positive\": 74.0}, {\"state\": \"WA\", \"date\": \"2020-03-14T00:00:00\", \"positive\": 568, \"negative\": 6001.0, \"pending\": null, \"death\": 37.0, \"total\": 6569, \"dateChecked\": \"2020-03-14T20:00:00Z\", \"positive_diff\": 111.0, \"negative_diff\": 1651.0, \"death_diff\": 6.0, \"total_10\": 656.9, \"daily_positive\": 111.0}, {\"state\": \"WA\", \"date\": \"2020-03-13T00:00:00\", \"positive\": 457, \"negative\": 4350.0, \"pending\": null, \"death\": 31.0, \"total\": 4807, \"dateChecked\": \"2020-03-13T20:00:00Z\", \"positive_diff\": 120.0, \"negative_diff\": 1313.0, \"death_diff\": 2.0, \"total_10\": 480.7, \"daily_positive\": 120.0}, {\"state\": \"WA\", \"date\": \"2020-03-12T00:00:00\", \"positive\": 337, \"negative\": 3037.0, \"pending\": null, \"death\": 29.0, \"total\": 3403, \"dateChecked\": \"2020-03-12T20:00:00Z\", \"positive_diff\": 70.0, \"negative_diff\": 862.0, \"death_diff\": 5.0, \"total_10\": 340.3, \"daily_positive\": 70.0}, {\"state\": \"WA\", \"date\": \"2020-03-11T00:00:00\", \"positive\": 267, \"negative\": 2175.0, \"pending\": null, \"death\": 24.0, \"total\": 2466, \"dateChecked\": \"2020-03-11T20:00:00Z\", \"positive_diff\": 105.0, \"negative_diff\": 1065.0, \"death_diff\": null, \"total_10\": 246.6, \"daily_positive\": 105.0}, {\"state\": \"WA\", \"date\": \"2020-03-10T00:00:00\", \"positive\": 162, \"negative\": 1110.0, \"pending\": null, \"death\": null, \"total\": 1272, \"dateChecked\": \"2020-03-10T20:00:00Z\", \"positive_diff\": 26.0, \"negative_diff\": 0.0, \"death_diff\": null, \"total_10\": 127.2, \"daily_positive\": 26.0}, {\"state\": \"WA\", \"date\": \"2020-03-09T00:00:00\", \"positive\": 136, \"negative\": 1110.0, \"pending\": null, \"death\": null, \"total\": 1246, \"dateChecked\": \"2020-03-09T20:00:00Z\", \"positive_diff\": 34.0, \"negative_diff\": 470.0, \"death_diff\": null, \"total_10\": 124.6, \"daily_positive\": 34.0}, {\"state\": \"WA\", \"date\": \"2020-03-08T00:00:00\", \"positive\": 102, \"negative\": 640.0, \"pending\": 60.0, \"death\": null, \"total\": 802, \"dateChecked\": \"2020-03-08T21:00:00Z\", \"positive_diff\": 0.0, \"negative_diff\": 270.0, \"death_diff\": null, \"total_10\": 80.2, \"daily_positive\": 0.0}, {\"state\": \"WA\", \"date\": \"2020-03-07T00:00:00\", \"positive\": 102, \"negative\": 370.0, \"pending\": 66.0, \"death\": null, \"total\": 538, \"dateChecked\": \"2020-03-07T21:00:00Z\", \"positive_diff\": 23.0, \"negative_diff\": 0.0, \"death_diff\": null, \"total_10\": 53.8, \"daily_positive\": 23.0}, {\"state\": \"WA\", \"date\": \"2020-03-06T00:00:00\", \"positive\": 79, \"negative\": 370.0, \"pending\": null, \"death\": null, \"total\": 449, \"dateChecked\": \"2020-03-06T21:00:00Z\", \"positive_diff\": 9.0, \"negative_diff\": null, \"death_diff\": null, \"total_10\": 44.9, \"daily_positive\": 9.0}, {\"state\": \"WA\", \"date\": \"2020-03-05T00:00:00\", \"positive\": 70, \"negative\": null, \"pending\": null, \"death\": null, \"total\": 70, \"dateChecked\": \"2020-03-05T21:00:00Z\", \"positive_diff\": 31.0, \"negative_diff\": null, \"death_diff\": null, \"total_10\": 7.0, \"daily_positive\": 31.0}, {\"state\": \"WA\", \"date\": \"2020-03-04T00:00:00\", \"positive\": 39, \"negative\": null, \"pending\": null, \"death\": null, \"total\": 39, \"dateChecked\": \"2020-03-04T21:00:00Z\", \"positive_diff\": null, \"negative_diff\": null, \"death_diff\": null, \"total_10\": 3.9, \"daily_positive\": null}], \"data-5524f3d9a011a4455f9aef2d5f2b332f\": [{\"state\": \"CA\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 924, \"negative\": 8787.0, \"pending\": null, \"death\": 18.0, \"total\": 9711, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"positive_diff\": 313.0, \"negative_diff\": 806.0, \"death_diff\": 5.0, \"total_10\": 971.1, \"daily_positive\": 313.0}, {\"state\": \"CA\", \"date\": \"2020-03-18T00:00:00\", \"positive\": 611, \"negative\": 7981.0, \"pending\": null, \"death\": 13.0, \"total\": 8592, \"dateChecked\": \"2020-03-18T20:00:00Z\", \"positive_diff\": 128.0, \"negative_diff\": 0.0, \"death_diff\": 2.0, \"total_10\": 859.2, \"daily_positive\": 128.0}, {\"state\": \"CA\", \"date\": \"2020-03-17T00:00:00\", \"positive\": 483, \"negative\": 7981.0, \"pending\": null, \"death\": 11.0, \"total\": 8407, \"dateChecked\": \"2020-03-17T20:00:00Z\", \"positive_diff\": 148.0, \"negative_diff\": 0.0, \"death_diff\": 5.0, \"total_10\": 840.7, \"daily_positive\": 148.0}, {\"state\": \"CA\", \"date\": \"2020-03-16T00:00:00\", \"positive\": 335, \"negative\": 7981.0, \"pending\": null, \"death\": 6.0, \"total\": 8316, \"dateChecked\": \"2020-03-16T20:00:00Z\", \"positive_diff\": 42.0, \"negative_diff\": 7065.0, \"death_diff\": 1.0, \"total_10\": 831.6, \"daily_positive\": 42.0}, {\"state\": \"CA\", \"date\": \"2020-03-15T00:00:00\", \"positive\": 293, \"negative\": 916.0, \"pending\": null, \"death\": 5.0, \"total\": 1209, \"dateChecked\": \"2020-03-15T20:00:00Z\", \"positive_diff\": 41.0, \"negative_diff\": 0.0, \"death_diff\": 0.0, \"total_10\": 120.9, \"daily_positive\": 41.0}, {\"state\": \"CA\", \"date\": \"2020-03-14T00:00:00\", \"positive\": 252, \"negative\": 916.0, \"pending\": null, \"death\": 5.0, \"total\": 1168, \"dateChecked\": \"2020-03-14T20:00:00Z\", \"positive_diff\": 50.0, \"negative_diff\": 0.0, \"death_diff\": 1.0, \"total_10\": 116.8, \"daily_positive\": 50.0}, {\"state\": \"CA\", \"date\": \"2020-03-13T00:00:00\", \"positive\": 202, \"negative\": 916.0, \"pending\": null, \"death\": 4.0, \"total\": 1118, \"dateChecked\": \"2020-03-13T20:00:00Z\", \"positive_diff\": 0.0, \"negative_diff\": 0.0, \"death_diff\": 0.0, \"total_10\": 111.8, \"daily_positive\": 0.0}, {\"state\": \"CA\", \"date\": \"2020-03-12T00:00:00\", \"positive\": 202, \"negative\": 916.0, \"pending\": null, \"death\": 4.0, \"total\": 1118, \"dateChecked\": \"2020-03-12T20:00:00Z\", \"positive_diff\": 45.0, \"negative_diff\": 0.0, \"death_diff\": null, \"total_10\": 111.8, \"daily_positive\": 45.0}, {\"state\": \"CA\", \"date\": \"2020-03-11T00:00:00\", \"positive\": 157, \"negative\": 916.0, \"pending\": null, \"death\": null, \"total\": 1073, \"dateChecked\": \"2020-03-11T20:00:00Z\", \"positive_diff\": 24.0, \"negative_diff\": 226.0, \"death_diff\": null, \"total_10\": 107.3, \"daily_positive\": 24.0}, {\"state\": \"CA\", \"date\": \"2020-03-10T00:00:00\", \"positive\": 133, \"negative\": 690.0, \"pending\": null, \"death\": null, \"total\": 823, \"dateChecked\": \"2020-03-10T20:00:00Z\", \"positive_diff\": 19.0, \"negative_diff\": 0.0, \"death_diff\": null, \"total_10\": 82.3, \"daily_positive\": 19.0}, {\"state\": \"CA\", \"date\": \"2020-03-09T00:00:00\", \"positive\": 114, \"negative\": 690.0, \"pending\": null, \"death\": null, \"total\": 804, \"dateChecked\": \"2020-03-09T20:00:00Z\", \"positive_diff\": 26.0, \"negative_diff\": 228.0, \"death_diff\": null, \"total_10\": 80.4, \"daily_positive\": 26.0}, {\"state\": \"CA\", \"date\": \"2020-03-08T00:00:00\", \"positive\": 88, \"negative\": 462.0, \"pending\": null, \"death\": null, \"total\": 550, \"dateChecked\": \"2020-03-08T21:00:00Z\", \"positive_diff\": 19.0, \"negative_diff\": 0.0, \"death_diff\": null, \"total_10\": 55.0, \"daily_positive\": 19.0}, {\"state\": \"CA\", \"date\": \"2020-03-07T00:00:00\", \"positive\": 69, \"negative\": 462.0, \"pending\": null, \"death\": null, \"total\": 531, \"dateChecked\": \"2020-03-07T21:00:00Z\", \"positive_diff\": 9.0, \"negative_diff\": 0.0, \"death_diff\": null, \"total_10\": 53.1, \"daily_positive\": 9.0}, {\"state\": \"CA\", \"date\": \"2020-03-06T00:00:00\", \"positive\": 60, \"negative\": 462.0, \"pending\": null, \"death\": null, \"total\": 522, \"dateChecked\": \"2020-03-06T21:00:00Z\", \"positive_diff\": 7.0, \"negative_diff\": 0.0, \"death_diff\": null, \"total_10\": 52.2, \"daily_positive\": 7.0}, {\"state\": \"CA\", \"date\": \"2020-03-05T00:00:00\", \"positive\": 53, \"negative\": 462.0, \"pending\": null, \"death\": null, \"total\": 515, \"dateChecked\": \"2020-03-05T21:00:00Z\", \"positive_diff\": 0.0, \"negative_diff\": 0.0, \"death_diff\": null, \"total_10\": 51.5, \"daily_positive\": 0.0}, {\"state\": \"CA\", \"date\": \"2020-03-04T00:00:00\", \"positive\": 53, \"negative\": 462.0, \"pending\": null, \"death\": null, \"total\": 515, \"dateChecked\": \"2020-03-04T21:00:00Z\", \"positive_diff\": null, \"negative_diff\": null, \"death_diff\": null, \"total_10\": 51.5, \"daily_positive\": null}], \"data-294eebc48941097d786524a29c373ee4\": [{\"state\": \"NY\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 4152, \"negative\": 18132.0, \"pending\": null, \"death\": 12.0, \"total\": 22284, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"positive_diff\": 1770.0, \"negative_diff\": 5917.0, \"death_diff\": 0.0, \"total_10\": 2228.4, \"daily_positive\": 1770.0}, {\"state\": \"NY\", \"date\": \"2020-03-18T00:00:00\", \"positive\": 2382, \"negative\": 12215.0, \"pending\": null, \"death\": 12.0, \"total\": 14597, \"dateChecked\": \"2020-03-18T20:00:00Z\", \"positive_diff\": 682.0, \"negative_diff\": 6709.0, \"death_diff\": 5.0, \"total_10\": 1459.7, \"daily_positive\": 682.0}, {\"state\": \"NY\", \"date\": \"2020-03-17T00:00:00\", \"positive\": 1700, \"negative\": 5506.0, \"pending\": null, \"death\": 7.0, \"total\": 7206, \"dateChecked\": \"2020-03-17T20:00:00Z\", \"positive_diff\": 750.0, \"negative_diff\": 1184.0, \"death_diff\": 0.0, \"total_10\": 720.6, \"daily_positive\": 750.0}, {\"state\": \"NY\", \"date\": \"2020-03-16T00:00:00\", \"positive\": 950, \"negative\": 4322.0, \"pending\": null, \"death\": 7.0, \"total\": 5272, \"dateChecked\": \"2020-03-16T20:00:00Z\", \"positive_diff\": 221.0, \"negative_diff\": -221.0, \"death_diff\": 4.0, \"total_10\": 527.2, \"daily_positive\": 221.0}, {\"state\": \"NY\", \"date\": \"2020-03-15T00:00:00\", \"positive\": 729, \"negative\": 4543.0, \"pending\": null, \"death\": 3.0, \"total\": 5272, \"dateChecked\": \"2020-03-15T20:00:00Z\", \"positive_diff\": 205.0, \"negative_diff\": 1764.0, \"death_diff\": null, \"total_10\": 527.2, \"daily_positive\": 205.0}, {\"state\": \"NY\", \"date\": \"2020-03-14T00:00:00\", \"positive\": 524, \"negative\": 2779.0, \"pending\": null, \"death\": null, \"total\": 3303, \"dateChecked\": \"2020-03-14T20:00:00Z\", \"positive_diff\": 103.0, \"negative_diff\": 0.0, \"death_diff\": null, \"total_10\": 330.3, \"daily_positive\": 103.0}, {\"state\": \"NY\", \"date\": \"2020-03-13T00:00:00\", \"positive\": 421, \"negative\": 2779.0, \"pending\": null, \"death\": null, \"total\": 3200, \"dateChecked\": \"2020-03-13T20:00:00Z\", \"positive_diff\": 205.0, \"negative_diff\": null, \"death_diff\": null, \"total_10\": 320.0, \"daily_positive\": 205.0}, {\"state\": \"NY\", \"date\": \"2020-03-12T00:00:00\", \"positive\": 216, \"negative\": null, \"pending\": null, \"death\": null, \"total\": 216, \"dateChecked\": \"2020-03-12T20:00:00Z\", \"positive_diff\": 0.0, \"negative_diff\": null, \"death_diff\": null, \"total_10\": 21.6, \"daily_positive\": 0.0}, {\"state\": \"NY\", \"date\": \"2020-03-11T00:00:00\", \"positive\": 216, \"negative\": null, \"pending\": null, \"death\": null, \"total\": 216, \"dateChecked\": \"2020-03-11T20:00:00Z\", \"positive_diff\": 43.0, \"negative_diff\": null, \"death_diff\": null, \"total_10\": 21.6, \"daily_positive\": 43.0}, {\"state\": \"NY\", \"date\": \"2020-03-10T00:00:00\", \"positive\": 173, \"negative\": 92.0, \"pending\": null, \"death\": null, \"total\": 265, \"dateChecked\": \"2020-03-10T20:00:00Z\", \"positive_diff\": 31.0, \"negative_diff\": 0.0, \"death_diff\": null, \"total_10\": 26.5, \"daily_positive\": 31.0}, {\"state\": \"NY\", \"date\": \"2020-03-09T00:00:00\", \"positive\": 142, \"negative\": 92.0, \"pending\": null, \"death\": null, \"total\": 234, \"dateChecked\": \"2020-03-09T20:00:00Z\", \"positive_diff\": 37.0, \"negative_diff\": 0.0, \"death_diff\": null, \"total_10\": 23.4, \"daily_positive\": 37.0}, {\"state\": \"NY\", \"date\": \"2020-03-08T00:00:00\", \"positive\": 105, \"negative\": 92.0, \"pending\": null, \"death\": null, \"total\": 197, \"dateChecked\": \"2020-03-08T21:00:00Z\", \"positive_diff\": 29.0, \"negative_diff\": 0.0, \"death_diff\": null, \"total_10\": 19.7, \"daily_positive\": 29.0}, {\"state\": \"NY\", \"date\": \"2020-03-07T00:00:00\", \"positive\": 76, \"negative\": 92.0, \"pending\": 236.0, \"death\": null, \"total\": 404, \"dateChecked\": \"2020-03-07T21:00:00Z\", \"positive_diff\": 43.0, \"negative_diff\": 0.0, \"death_diff\": null, \"total_10\": 40.4, \"daily_positive\": 43.0}, {\"state\": \"NY\", \"date\": \"2020-03-06T00:00:00\", \"positive\": 33, \"negative\": 92.0, \"pending\": 236.0, \"death\": null, \"total\": 361, \"dateChecked\": \"2020-03-06T21:00:00Z\", \"positive_diff\": 11.0, \"negative_diff\": 16.0, \"death_diff\": null, \"total_10\": 36.1, \"daily_positive\": 11.0}, {\"state\": \"NY\", \"date\": \"2020-03-05T00:00:00\", \"positive\": 22, \"negative\": 76.0, \"pending\": 24.0, \"death\": null, \"total\": 122, \"dateChecked\": \"2020-03-05T21:00:00Z\", \"positive_diff\": 16.0, \"negative_diff\": 28.0, \"death_diff\": null, \"total_10\": 12.2, \"daily_positive\": 16.0}, {\"state\": \"NY\", \"date\": \"2020-03-04T00:00:00\", \"positive\": 6, \"negative\": 48.0, \"pending\": 24.0, \"death\": null, \"total\": 78, \"dateChecked\": \"2020-03-04T21:00:00Z\", \"positive_diff\": null, \"negative_diff\": null, \"death_diff\": null, \"total_10\": 7.8, \"daily_positive\": null}]}}, {\"mode\": \"vega-lite\"});\n",
       "</script>"
       "alt.HConcatChart(...)"
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# produce the charts for a few states\n",
    "\n",
    "charts=[]\n",
    "for state in ['WA', 'CA', 'NY']: \n",
    "    state_df = tdf_diff[tdf_diff['state'] == state].copy()\n",
    "    state_df.loc[:,'daily_positive'] = state_df['positive'][::-1].diff()\n",
    "    state_df.loc[:,'total_10'] = state_df['total']/10.\n",
    "\n",
    "    base = alt.Chart(state_df, title=state).encode(alt.X('date', axis=alt.Axis(title='Date'))).properties(width=250, height=150)\n",
    "    dailies = base.mark_bar(size=10).encode(alt.Y('daily_positive', axis=alt.Axis(title='Daily positive')))\n",
    "\n",
    "    totals = base.mark_line(color='red').encode(alt.Y('total_10', axis=alt.Axis(title='Total/10'))) \n",
    "    positives = totals.mark_line(color='orange').encode(alt.Y('positive', axis=alt.Axis(title='Positive')))\n",
    "    cumulative = totals + positives\n",
    "\n",
    "    charts.append(alt.layer(dailies, cumulative).resolve_scale(y='independent'))\n",
    "\n",
    "\n",
    "alt.hconcat(*charts)"
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Counts per 100k"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "outputs": [],
   "source": [
    "pop_df = pd.read_csv('../../data/geodata/us_pop_fung_2019.csv').set_index('ST')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Most recent test date 2020-03-19 00:00:00\n",
      "56 states/territories have data on this date.\n"
     ]
    }
   ],
   "source": [
    "most_recent_test_date = data_df['date'].max()\n",
    "most_recent_df = data_df[data_df['date'] == most_recent_test_date].set_index('state')\n",
    "print(\"Most recent test date\", most_recent_test_date)\n",
    "print(len(most_recent_df), \"states/territories have data on this date.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [],
   "source": [
    "most_recent_df['total/100k'] = (most_recent_df['total'] / pop_df['Population']) * 100000\n",
    "most_recent_df = most_recent_df.reset_index()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>state</th>\n",
       "      <th>date</th>\n",
       "      <th>positive</th>\n",
       "      <th>negative</th>\n",
       "      <th>pending</th>\n",
       "      <th>death</th>\n",
       "      <th>total</th>\n",
       "      <th>dateChecked</th>\n",
       "      <th>total/100k</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>AK</td>\n",
       "      <td>2020-03-19</td>\n",
       "      <td>6</td>\n",
       "      <td>400.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>406</td>\n",
       "      <td>2020-03-19T20:00:00Z</td>\n",
       "      <td>55.498978</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>AL</td>\n",
       "      <td>2020-03-19</td>\n",
       "      <td>68</td>\n",
       "      <td>28.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "      <td>96</td>\n",
       "      <td>2020-03-19T20:00:00Z</td>\n",
       "      <td>1.957911</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>AR</td>\n",
       "      <td>2020-03-19</td>\n",
       "      <td>46</td>\n",
       "      <td>310.0</td>\n",
       "      <td>113.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>469</td>\n",
       "      <td>2020-03-19T20:00:00Z</td>\n",
       "      <td>15.540994</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>AS</td>\n",
       "      <td>2020-03-19</td>\n",
       "      <td>0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>2020-03-19T20:00:00Z</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>AZ</td>\n",
       "      <td>2020-03-19</td>\n",
       "      <td>44</td>\n",
       "      <td>175.0</td>\n",
       "      <td>130.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>349</td>\n",
       "      <td>2020-03-19T20:00:00Z</td>\n",
       "      <td>4.794801</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  state       date  positive  negative  pending  death  total  \\\n",
       "0    AK 2020-03-19         6     400.0      NaN    NaN    406   \n",
       "1    AL 2020-03-19        68      28.0      NaN    0.0     96   \n",
       "2    AR 2020-03-19        46     310.0    113.0    NaN    469   \n",
       "3    AS 2020-03-19         0       NaN      NaN    0.0      0   \n",
       "4    AZ 2020-03-19        44     175.0    130.0    0.0    349   \n",
       "\n",
       "            dateChecked  total/100k  \n",
       "0  2020-03-19T20:00:00Z   55.498978  \n",
       "1  2020-03-19T20:00:00Z    1.957911  \n",
       "2  2020-03-19T20:00:00Z   15.540994  \n",
       "3  2020-03-19T20:00:00Z         NaN  \n",
       "4  2020-03-19T20:00:00Z    4.794801  "
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "most_recent_df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<div id=\"altair-viz-e7f6c101686c406b93be99359dbeb66b\"></div>\n",
       "<script type=\"text/javascript\">\n",
       "  (function(spec, embedOpt){\n",
       "    const outputDiv = document.getElementById(\"altair-viz-e7f6c101686c406b93be99359dbeb66b\");\n",
       "    const paths = {\n",
       "      \"vega\": \"https://cdn.jsdelivr.net/npm//vega@5?noext\",\n",
       "      \"vega-lib\": \"https://cdn.jsdelivr.net/npm//vega-lib?noext\",\n",
       "      \"vega-lite\": \"https://cdn.jsdelivr.net/npm//vega-lite@4.0.2?noext\",\n",
       "      \"vega-embed\": \"https://cdn.jsdelivr.net/npm//vega-embed@6?noext\",\n",
       "    };\n",
       "\n",
       "    function loadScript(lib) {\n",
       "      return new Promise(function(resolve, reject) {\n",
       "        var s = document.createElement('script');\n",
       "        s.src = paths[lib];\n",
       "        s.async = true;\n",
       "        s.onload = () => resolve(paths[lib]);\n",
       "        s.onerror = () => reject(`Error loading script: ${paths[lib]}`);\n",
       "        document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
       "      });\n",
       "    }\n",
       "\n",
       "    function showError(err) {\n",
       "      outputDiv.innerHTML = `<div class=\"error\" style=\"color:red;\">${err}</div>`;\n",
       "      throw err;\n",
       "    }\n",
       "\n",
       "    function displayChart(vegaEmbed) {\n",
       "      vegaEmbed(outputDiv, spec, embedOpt)\n",
       "        .catch(err => showError(`Javascript Error: ${err.message}<br>This usually means there's a typo in your chart specification. See the javascript console for the full traceback.`));\n",
       "    }\n",
       "\n",
       "    if(typeof define === \"function\" && define.amd) {\n",
       "      requirejs.config({paths});\n",
       "      require([\"vega-embed\"], displayChart, err => showError(`Error loading script: ${err.message}`));\n",
       "    } else if (typeof vegaEmbed === \"function\") {\n",
       "      displayChart(vegaEmbed);\n",
       "    } else {\n",
       "      loadScript(\"vega\")\n",
       "        .then(() => loadScript(\"vega-lite\"))\n",
       "        .then(() => loadScript(\"vega-embed\"))\n",
       "        .catch(showError)\n",
       "        .then(() => displayChart(vegaEmbed));\n",
       "    }\n",
       "  })({\"config\": {\"view\": {\"continuousWidth\": 400, \"continuousHeight\": 300}}, \"data\": {\"name\": \"data-105f25aa4bb22f20e7892e19480d209c\"}, \"mark\": \"bar\", \"encoding\": {\"x\": {\"type\": \"nominal\", \"field\": \"state\", \"sort\": \"y\"}, \"y\": {\"type\": \"quantitative\", \"field\": \"total/100k\"}}, \"title\": \"Tests per 100k\", \"$schema\": \"https://vega.github.io/schema/vega-lite/v4.0.2.json\", \"datasets\": {\"data-105f25aa4bb22f20e7892e19480d209c\": [{\"state\": \"AL\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 68, \"negative\": 28.0, \"pending\": null, \"death\": 0.0, \"total\": 96, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 1.9579110312990435}, {\"state\": \"OH\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 119, \"negative\": 140.0, \"pending\": null, \"death\": null, \"total\": 259, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 2.2157394495726788}, {\"state\": \"MD\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 107, \"negative\": 94.0, \"pending\": null, \"death\": 1.0, \"total\": 201, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 3.3246880417091216}, {\"state\": \"IA\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 38, \"negative\": 83.0, \"pending\": null, \"death\": null, \"total\": 121, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 3.83509716107725}, {\"state\": \"AZ\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 44, \"negative\": 175.0, \"pending\": 130.0, \"death\": 0.0, \"total\": 349, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 4.794801061780531}, {\"state\": \"MO\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 24, \"negative\": 308.0, \"pending\": null, \"death\": 1.0, \"total\": 332, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 5.409432094356138}, {\"state\": \"IN\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 56, \"negative\": 324.0, \"pending\": null, \"death\": 2.0, \"total\": 380, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 5.644498492993172}, {\"state\": \"DE\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 30, \"negative\": 36.0, \"pending\": null, \"death\": 0.0, \"total\": 66, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 6.777822963264199}, {\"state\": \"TN\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 154, \"negative\": 349.0, \"pending\": null, \"death\": null, \"total\": 503, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 7.361147250165151}, {\"state\": \"TX\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 143, \"negative\": 2212.0, \"pending\": null, \"death\": 3.0, \"total\": 2355, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 8.121843236975625}, {\"state\": \"WV\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 2, \"negative\": 143.0, \"pending\": 3.0, \"death\": 0.0, \"total\": 148, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 8.281355702692615}, {\"state\": \"HI\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 16, \"negative\": 93.0, \"pending\": 9.0, \"death\": null, \"total\": 118, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 8.334086697102563}, {\"state\": \"KY\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 35, \"negative\": 454.0, \"pending\": null, \"death\": 1.0, \"total\": 489, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 10.945295235349588}, {\"state\": \"NJ\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 742, \"negative\": 210.0, \"pending\": 74.0, \"death\": 9.0, \"total\": 1026, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 11.551205277076937}, {\"state\": \"SC\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 60, \"negative\": 583.0, \"pending\": null, \"death\": 1.0, \"total\": 643, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 12.488555394609216}, {\"state\": \"FL\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 390, \"negative\": 1533.0, \"pending\": 1019.0, \"death\": 8.0, \"total\": 2942, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 13.697904951531905}, {\"state\": \"NE\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 27, \"negative\": 240.0, \"pending\": null, \"death\": 0.0, \"total\": 267, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 13.802672445523383}, {\"state\": \"PA\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 185, \"negative\": 1608.0, \"pending\": null, \"death\": 1.0, \"total\": 1793, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 14.005636155444282}, {\"state\": \"KS\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 34, \"negative\": 417.0, \"pending\": null, \"death\": 1.0, \"total\": 451, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 15.480651931099771}, {\"state\": \"AR\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 46, \"negative\": 310.0, \"pending\": 113.0, \"death\": null, \"total\": 469, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 15.540993927745976}, {\"state\": \"GA\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 287, \"negative\": 1544.0, \"pending\": null, \"death\": 10.0, \"total\": 1831, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 17.245239263802524}, {\"state\": \"LA\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 347, \"negative\": 458.0, \"pending\": null, \"death\": 8.0, \"total\": 805, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 17.31631902811783}, {\"state\": \"OK\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 44, \"negative\": 466.0, \"pending\": 250.0, \"death\": 1.0, \"total\": 760, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 19.206610308743734}, {\"state\": \"CT\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 96, \"negative\": 604.0, \"pending\": null, \"death\": 1.0, \"total\": 700, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 19.633763004212565}, {\"state\": \"MS\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 50, \"negative\": 552.0, \"pending\": null, \"death\": null, \"total\": 602, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 20.227481890187622}, {\"state\": \"VA\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 94, \"negative\": 1829.0, \"pending\": null, \"death\": 2.0, \"total\": 1923, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 22.52938573506778}, {\"state\": \"NC\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 97, \"negative\": 2408.0, \"pending\": null, \"death\": 0.0, \"total\": 2505, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 23.88424806666308}, {\"state\": \"MI\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 336, \"negative\": 2113.0, \"pending\": null, \"death\": 3.0, \"total\": 2449, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 24.522229566319012}, {\"state\": \"CA\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 924, \"negative\": 8787.0, \"pending\": null, \"death\": 18.0, \"total\": 9711, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 24.577204881638778}, {\"state\": \"IL\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 426, \"negative\": 2725.0, \"pending\": null, \"death\": 4.0, \"total\": 3151, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 24.86619721032991}, {\"state\": \"ID\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 11, \"negative\": 457.0, \"pending\": null, \"death\": null, \"total\": 468, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 26.1151241723933}, {\"state\": \"DC\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 39, \"negative\": 153.0, \"pending\": 11.0, \"death\": 0.0, \"total\": 203, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 28.76376728837023}, {\"state\": \"WI\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 155, \"negative\": 2192.0, \"pending\": null, \"death\": null, \"total\": 2347, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 40.309602478963264}, {\"state\": \"CO\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 216, \"negative\": 2112.0, \"pending\": null, \"death\": 2.0, \"total\": 2328, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 40.42553782635634}, {\"state\": \"OR\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 88, \"negative\": 1329.0, \"pending\": 437.0, \"death\": 3.0, \"total\": 1854, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 43.95722160959775}, {\"state\": \"MA\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 328, \"negative\": 2804.0, \"pending\": null, \"death\": null, \"total\": 3132, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 45.067971047713776}, {\"state\": \"WY\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 18, \"negative\": 271.0, \"pending\": null, \"death\": null, \"total\": 289, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 49.934428665472154}, {\"state\": \"UT\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 78, \"negative\": 1526.0, \"pending\": null, \"death\": 0.0, \"total\": 1604, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 50.03184695495075}, {\"state\": \"MN\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 89, \"negative\": 2949.0, \"pending\": null, \"death\": null, \"total\": 3038, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 53.86876306822856}, {\"state\": \"AK\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 6, \"negative\": 400.0, \"pending\": null, \"death\": null, \"total\": 406, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 55.49897818999514}, {\"state\": \"NV\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 95, \"negative\": 1626.0, \"pending\": null, \"death\": 1.0, \"total\": 1721, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 55.873793405269076}, {\"state\": \"NH\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 39, \"negative\": 621.0, \"pending\": 231.0, \"death\": null, \"total\": 891, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 65.52863071638016}, {\"state\": \"ND\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 15, \"negative\": 493.0, \"pending\": null, \"death\": 0.0, \"total\": 508, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 66.66124278602003}, {\"state\": \"MT\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 12, \"negative\": 761.0, \"pending\": 0.0, \"death\": null, \"total\": 773, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 72.3255905342363}, {\"state\": \"RI\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 33, \"negative\": 540.0, \"pending\": 334.0, \"death\": null, \"total\": 907, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 85.61765064033885}, {\"state\": \"VT\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 22, \"negative\": 645.0, \"pending\": null, \"death\": null, \"total\": 667, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 106.89290997116937}, {\"state\": \"SD\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 11, \"negative\": 551.0, \"pending\": 385.0, \"death\": 1.0, \"total\": 947, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 107.04689603564763}, {\"state\": \"NY\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 4152, \"negative\": 18132.0, \"pending\": null, \"death\": 12.0, \"total\": 22284, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 114.5497217707339}, {\"state\": \"NM\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 35, \"negative\": 2762.0, \"pending\": null, \"death\": null, \"total\": 2797, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 133.39189795639035}, {\"state\": \"ME\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 53, \"negative\": 2004.0, \"pending\": null, \"death\": null, \"total\": 2057, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 153.02645713622553}, {\"state\": \"WA\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 1187, \"negative\": 15918.0, \"pending\": null, \"death\": 66.0, \"total\": 17105, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": 224.62561194228203}, {\"state\": \"AS\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 0, \"negative\": null, \"pending\": null, \"death\": 0.0, \"total\": 0, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": null}, {\"state\": \"GU\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 12, \"negative\": 69.0, \"pending\": null, \"death\": null, \"total\": 81, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": null}, {\"state\": \"MP\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 0, \"negative\": null, \"pending\": null, \"death\": 0.0, \"total\": 0, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": null}, {\"state\": \"PR\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 5, \"negative\": 56.0, \"pending\": 29.0, \"death\": null, \"total\": 90, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": null}, {\"state\": \"VI\", \"date\": \"2020-03-19T00:00:00\", \"positive\": 3, \"negative\": null, \"pending\": null, \"death\": 0.0, \"total\": 3, \"dateChecked\": \"2020-03-19T20:00:00Z\", \"total/100k\": null}]}}, {\"mode\": \"vega-lite\"});\n",
       "</script>"
      ],
      "text/plain": [
       "alt.Chart(...)"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chart = alt.Chart(most_recent_df.sort_values('total/100k'), title=\"Tests per 100k\")\n",
    "chart.mark_bar().encode(alt.X('state', sort='y'), alt.Y('total/100k'))"
   ]
  }
 ],
 "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.3"