{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Indexes\n",
    "\n",
    "Today we're going to be talking about pandas' [`Index`es](http://pandas.pydata.org/pandas-docs/version/0.18.0/api.html#index).\n",
    "They're essential to pandas, but can be a difficult concept to grasp at first.\n",
    "I suspect this is partly because they're unlike what you'll find in SQL or R.\n",
    "\n",
    "`Index`es offer\n",
    "\n",
    "- a metadata container\n",
    "- easy label-based row selection and assignment\n",
    "- easy label-based alignment in operations\n",
    "\n",
    "One of my first tasks when analyzing a new dataset is to identify a unique identifier for each observation, and set that as the index. It could be a simple integer, or like in our first chapter, it could be several columns (`carrier`, `origin` `dest`, `tail_num` `date`).\n",
    "\n",
    "To demonstrate the benefits of proper `Index` use, we'll first fetch some weather data from sensors at a bunch of airports across the US.\n",
    "See [here](https://github.com/akrherz/iem/blob/master/scripts/asos/iem_scraper_example.py) for the example scraper I based this off of.\n",
    "Those uninterested in the details of fetching and prepping the data and [skip past it](#set-operations).\n",
    "\n",
    "At a high level, here's how we'll fetch the data: the sensors are broken up by \"network\" (states).\n",
    "We'll make one API call per state to get the list of airport IDs per network (using `get_ids` below).\n",
    "Once we have the IDs, we'll again make one call per state getting the actual observations (in `get_weather`).\n",
    "Feel free to skim the code below, I'll highlight the interesting bits.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "\n",
    "import os\n",
    "import json\n",
    "import glob\n",
    "import datetime\n",
    "from io import StringIO\n",
    "\n",
    "import requests\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import seaborn as sns\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "import prep\n",
    "\n",
    "sns.set_style('ticks')\n",
    "pd.options.display.max_rows = 10\n",
    "# States are broken into networks. The networks have a list of ids, each representing a station.\n",
    "# We will take that list of ids and pass them as query parameters to the URL we built up ealier.\n",
    "states = \"\"\"AK AL AR AZ CA CO CT DE FL GA HI IA ID IL IN KS KY LA MA MD ME\n",
    " MI MN MO MS MT NC ND NE NH NJ NM NV NY OH OK OR PA RI SC SD TN TX UT VA VT\n",
    " WA WI WV WY\"\"\".split()\n",
    "\n",
    "# IEM has Iowa AWOS sites in its own labeled network\n",
    "networks = ['AWOS'] + ['{}_ASOS'.format(state) for state in states]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_weather(stations, start=pd.Timestamp('2017-01-01'),\n",
    "                end=pd.Timestamp('2017-01-31')):\n",
    "    '''\n",
    "    Fetch weather data from MESONet between ``start`` and ``stop``.\n",
    "    '''\n",
    "    url = (\"http://mesonet.agron.iastate.edu/cgi-bin/request/asos.py?\"\n",
    "           \"&data=tmpf&data=relh&data=sped&data=mslp&data=p01i&data=v\"\n",
    "           \"sby&data=gust_mph&data=skyc1&data=skyc2&data=skyc3\"\n",
    "           \"&tz=Etc/UTC&format=comma&latlon=no\"\n",
    "           \"&{start:year1=%Y&month1=%m&day1=%d}\"\n",
    "           \"&{end:year2=%Y&month2=%m&day2=%d}&{stations}\")\n",
    "    stations = \"&\".join(\"station=%s\" % s for s in stations)\n",
    "    weather = (pd.read_csv(url.format(start=start, end=end, stations=stations),\n",
    "                           comment=\"#\")\n",
    "                 .rename(columns={\"valid\": \"date\"})\n",
    "                 .rename(columns=str.strip)\n",
    "                 .assign(date=lambda df: pd.to_datetime(df['date']))\n",
    "                 .set_index([\"station\", \"date\"])\n",
    "                 .sort_index())\n",
    "    float_cols = ['tmpf', 'relh', 'sped', 'mslp', 'p01i', 'vsby', \"gust_mph\"]\n",
    "    weather[float_cols] = weather[float_cols].apply(pd.to_numeric, errors=\"corce\")\n",
    "    return weather"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def get_ids(network):\n",
    "    url = \"http://mesonet.agron.iastate.edu/geojson/network.php?network={}\"\n",
    "    r = requests.get(url.format(network))\n",
    "    md = pd.io.json.json_normalize(r.json()['features'])\n",
    "    md['network'] = network\n",
    "    return md"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "There isn't too much in `get_weather` worth mentioning, just grabbing some CSV files from various URLs.\n",
    "They put metadata in the \"CSV\"s at the top of the file as lines prefixed by a `#`.\n",
    "Pandas will ignore these with the `comment='#'` parameter.\n",
    "\n",
    "I do want to talk briefly about the gem of a method that is [`json_normalize`](http://pandas.pydata.org/pandas-docs/version/0.18.0/generated/pandas.io.json.json_normalize.html)  .\n",
    "The weather API returns some slightly-nested data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'geometry': {'coordinates': [-94.2724, 43.0796], 'type': 'Point'},\n",
       "  'id': 'AXA',\n",
       "  'properties': {'climate_site': 'IA0133',\n",
       "   'country': 'US',\n",
       "   'county': 'Kossuth',\n",
       "   'elevation': 368.8,\n",
       "   'ncdc81': 'USC00130133',\n",
       "   'sid': 'AXA',\n",
       "   'sname': 'ALGONA',\n",
       "   'state': 'IA',\n",
       "   'tzname': 'America/Chicago',\n",
       "   'ugc_county': 'IAC109',\n",
       "   'ugc_zone': 'IAZ005',\n",
       "   'wfo': 'DMX'},\n",
       "  'type': 'Feature'},\n",
       " {'geometry': {'coordinates': [-93.5695, 41.6878], 'type': 'Point'},\n",
       "  'id': 'IKV',\n",
       "  'properties': {'climate_site': 'IA0241',\n",
       "   'country': 'US',\n",
       "   'county': 'Polk',\n",
       "   'elevation': 270.7,\n",
       "   'ncdc81': 'USC00130241',\n",
       "   'sid': 'IKV',\n",
       "   'sname': 'ANKENY',\n",
       "   'state': 'IA',\n",
       "   'tzname': 'America/Chicago',\n",
       "   'ugc_county': 'IAC153',\n",
       "   'ugc_zone': 'IAZ060',\n",
       "   'wfo': 'DMX'},\n",
       "  'type': 'Feature'}]"
      ]
     },
     "execution_count": 109,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "url = \"http://mesonet.agron.iastate.edu/geojson/network.php?network={}\"\n",
    "r = requests.get(url.format(\"AWOS\"))\n",
    "js = r.json()\n",
    "\n",
    "js['features'][:2]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we just pass that list off to the `DataFrame` constructor, we get this."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>geometry</th>\n",
       "      <th>id</th>\n",
       "      <th>properties</th>\n",
       "      <th>type</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>{'type': 'Point', 'coordinates': [-94.2724, 43...</td>\n",
       "      <td>AXA</td>\n",
       "      <td>{'ugc_county': 'IAC109', 'sname': 'ALGONA', 'u...</td>\n",
       "      <td>Feature</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>{'type': 'Point', 'coordinates': [-93.5695, 41...</td>\n",
       "      <td>IKV</td>\n",
       "      <td>{'ugc_county': 'IAC153', 'sname': 'ANKENY', 'u...</td>\n",
       "      <td>Feature</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>{'type': 'Point', 'coordinates': [-95.0465, 41...</td>\n",
       "      <td>AIO</td>\n",
       "      <td>{'ugc_county': 'IAC029', 'sname': 'ATLANTIC', ...</td>\n",
       "      <td>Feature</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>{'type': 'Point', 'coordinates': [-94.9204, 41...</td>\n",
       "      <td>ADU</td>\n",
       "      <td>{'ugc_county': 'IAC009', 'sname': 'AUDUBON', '...</td>\n",
       "      <td>Feature</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>{'type': 'Point', 'coordinates': [-93.8486, 42...</td>\n",
       "      <td>BNW</td>\n",
       "      <td>{'ugc_county': 'IAC015', 'sname': 'BOONE MUNI'...</td>\n",
       "      <td>Feature</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                            geometry   id  \\\n",
       "0  {'type': 'Point', 'coordinates': [-94.2724, 43...  AXA   \n",
       "1  {'type': 'Point', 'coordinates': [-93.5695, 41...  IKV   \n",
       "2  {'type': 'Point', 'coordinates': [-95.0465, 41...  AIO   \n",
       "3  {'type': 'Point', 'coordinates': [-94.9204, 41...  ADU   \n",
       "4  {'type': 'Point', 'coordinates': [-93.8486, 42...  BNW   \n",
       "\n",
       "                                          properties     type  \n",
       "0  {'ugc_county': 'IAC109', 'sname': 'ALGONA', 'u...  Feature  \n",
       "1  {'ugc_county': 'IAC153', 'sname': 'ANKENY', 'u...  Feature  \n",
       "2  {'ugc_county': 'IAC029', 'sname': 'ATLANTIC', ...  Feature  \n",
       "3  {'ugc_county': 'IAC009', 'sname': 'AUDUBON', '...  Feature  \n",
       "4  {'ugc_county': 'IAC015', 'sname': 'BOONE MUNI'...  Feature  "
      ]
     },
     "execution_count": 111,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.DataFrame(js['features']).head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In general, DataFrames don't handle nested data that well.\n",
    "It's often better to normalize it somehow.\n",
    "In this case, we can \"lift\"\n",
    "the nested items (`geometry.coordinates`, `properties.sid`, and `properties.sname`)\n",
    "up to the top level."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>geometry.coordinates</th>\n",
       "      <th>geometry.type</th>\n",
       "      <th>id</th>\n",
       "      <th>properties.climate_site</th>\n",
       "      <th>properties.country</th>\n",
       "      <th>properties.county</th>\n",
       "      <th>properties.elevation</th>\n",
       "      <th>properties.ncdc81</th>\n",
       "      <th>properties.sid</th>\n",
       "      <th>properties.sname</th>\n",
       "      <th>properties.state</th>\n",
       "      <th>properties.tzname</th>\n",
       "      <th>properties.ugc_county</th>\n",
       "      <th>properties.ugc_zone</th>\n",
       "      <th>properties.wfo</th>\n",
       "      <th>type</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>[-94.2724, 43.0796]</td>\n",
       "      <td>Point</td>\n",
       "      <td>AXA</td>\n",
       "      <td>IA0133</td>\n",
       "      <td>US</td>\n",
       "      <td>Kossuth</td>\n",
       "      <td>368.8</td>\n",
       "      <td>USC00130133</td>\n",
       "      <td>AXA</td>\n",
       "      <td>ALGONA</td>\n",
       "      <td>IA</td>\n",
       "      <td>America/Chicago</td>\n",
       "      <td>IAC109</td>\n",
       "      <td>IAZ005</td>\n",
       "      <td>DMX</td>\n",
       "      <td>Feature</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>[-93.5695, 41.6878]</td>\n",
       "      <td>Point</td>\n",
       "      <td>IKV</td>\n",
       "      <td>IA0241</td>\n",
       "      <td>US</td>\n",
       "      <td>Polk</td>\n",
       "      <td>270.7</td>\n",
       "      <td>USC00130241</td>\n",
       "      <td>IKV</td>\n",
       "      <td>ANKENY</td>\n",
       "      <td>IA</td>\n",
       "      <td>America/Chicago</td>\n",
       "      <td>IAC153</td>\n",
       "      <td>IAZ060</td>\n",
       "      <td>DMX</td>\n",
       "      <td>Feature</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>[-95.0465, 41.4059]</td>\n",
       "      <td>Point</td>\n",
       "      <td>AIO</td>\n",
       "      <td>IA0364</td>\n",
       "      <td>US</td>\n",
       "      <td>Cass</td>\n",
       "      <td>351.7</td>\n",
       "      <td>USC00130364</td>\n",
       "      <td>AIO</td>\n",
       "      <td>ATLANTIC</td>\n",
       "      <td>IA</td>\n",
       "      <td>America/Chicago</td>\n",
       "      <td>IAC029</td>\n",
       "      <td>IAZ070</td>\n",
       "      <td>DMX</td>\n",
       "      <td>Feature</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>[-94.9204, 41.6994]</td>\n",
       "      <td>Point</td>\n",
       "      <td>ADU</td>\n",
       "      <td>IA0385</td>\n",
       "      <td>US</td>\n",
       "      <td>Audubon</td>\n",
       "      <td>399.3</td>\n",
       "      <td>USC00130385</td>\n",
       "      <td>ADU</td>\n",
       "      <td>AUDUBON</td>\n",
       "      <td>IA</td>\n",
       "      <td>America/Chicago</td>\n",
       "      <td>IAC009</td>\n",
       "      <td>IAZ057</td>\n",
       "      <td>DMX</td>\n",
       "      <td>Feature</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>[-93.8486, 42.0486]</td>\n",
       "      <td>Point</td>\n",
       "      <td>BNW</td>\n",
       "      <td>IA0807</td>\n",
       "      <td>US</td>\n",
       "      <td>Boone</td>\n",
       "      <td>349.3</td>\n",
       "      <td>USC00130807</td>\n",
       "      <td>BNW</td>\n",
       "      <td>BOONE MUNI</td>\n",
       "      <td>IA</td>\n",
       "      <td>America/Chicago</td>\n",
       "      <td>IAC015</td>\n",
       "      <td>IAZ047</td>\n",
       "      <td>DMX</td>\n",
       "      <td>Feature</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>40</th>\n",
       "      <td>[-95.4112, 40.7533]</td>\n",
       "      <td>Point</td>\n",
       "      <td>SDA</td>\n",
       "      <td>IA7613</td>\n",
       "      <td>US</td>\n",
       "      <td>Fremont</td>\n",
       "      <td>296.0</td>\n",
       "      <td>USC00137613</td>\n",
       "      <td>SDA</td>\n",
       "      <td>SHENANDOAH MUNI</td>\n",
       "      <td>IA</td>\n",
       "      <td>America/Chicago</td>\n",
       "      <td>IAC071</td>\n",
       "      <td>IAZ090</td>\n",
       "      <td>OAX</td>\n",
       "      <td>Feature</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>41</th>\n",
       "      <td>[-95.2399, 42.5972]</td>\n",
       "      <td>Point</td>\n",
       "      <td>SLB</td>\n",
       "      <td>IA7979</td>\n",
       "      <td>US</td>\n",
       "      <td>Buena Vista</td>\n",
       "      <td>449.9</td>\n",
       "      <td>USC00137979</td>\n",
       "      <td>SLB</td>\n",
       "      <td>Storm Lake</td>\n",
       "      <td>IA</td>\n",
       "      <td>America/Chicago</td>\n",
       "      <td>IAC021</td>\n",
       "      <td>IAZ301</td>\n",
       "      <td>FSD</td>\n",
       "      <td>Feature</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>42</th>\n",
       "      <td>[-92.0248, 42.2176]</td>\n",
       "      <td>Point</td>\n",
       "      <td>VTI</td>\n",
       "      <td>IA8568</td>\n",
       "      <td>US</td>\n",
       "      <td>Benton</td>\n",
       "      <td>255.0</td>\n",
       "      <td>USC00138568</td>\n",
       "      <td>VTI</td>\n",
       "      <td>VINTON</td>\n",
       "      <td>IA</td>\n",
       "      <td>America/Chicago</td>\n",
       "      <td>IAC011</td>\n",
       "      <td>IAZ051</td>\n",
       "      <td>DVN</td>\n",
       "      <td>Feature</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>43</th>\n",
       "      <td>[-91.6748, 41.2751]</td>\n",
       "      <td>Point</td>\n",
       "      <td>AWG</td>\n",
       "      <td>IA8688</td>\n",
       "      <td>US</td>\n",
       "      <td>Washington</td>\n",
       "      <td>228.9</td>\n",
       "      <td>USC00138688</td>\n",
       "      <td>AWG</td>\n",
       "      <td>WASHINGTON</td>\n",
       "      <td>IA</td>\n",
       "      <td>America/Chicago</td>\n",
       "      <td>IAC183</td>\n",
       "      <td>IAZ077</td>\n",
       "      <td>DVN</td>\n",
       "      <td>Feature</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>44</th>\n",
       "      <td>[-93.8691, 42.4392]</td>\n",
       "      <td>Point</td>\n",
       "      <td>EBS</td>\n",
       "      <td>IA8806</td>\n",
       "      <td>US</td>\n",
       "      <td>Hamilton</td>\n",
       "      <td>337.4</td>\n",
       "      <td>USC00138806</td>\n",
       "      <td>EBS</td>\n",
       "      <td>Webster City</td>\n",
       "      <td>IA</td>\n",
       "      <td>America/Chicago</td>\n",
       "      <td>IAC079</td>\n",
       "      <td>IAZ036</td>\n",
       "      <td>DMX</td>\n",
       "      <td>Feature</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>45 rows × 16 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "   geometry.coordinates geometry.type   id properties.climate_site  \\\n",
       "0   [-94.2724, 43.0796]         Point  AXA                  IA0133   \n",
       "1   [-93.5695, 41.6878]         Point  IKV                  IA0241   \n",
       "2   [-95.0465, 41.4059]         Point  AIO                  IA0364   \n",
       "3   [-94.9204, 41.6994]         Point  ADU                  IA0385   \n",
       "4   [-93.8486, 42.0486]         Point  BNW                  IA0807   \n",
       "..                  ...           ...  ...                     ...   \n",
       "40  [-95.4112, 40.7533]         Point  SDA                  IA7613   \n",
       "41  [-95.2399, 42.5972]         Point  SLB                  IA7979   \n",
       "42  [-92.0248, 42.2176]         Point  VTI                  IA8568   \n",
       "43  [-91.6748, 41.2751]         Point  AWG                  IA8688   \n",
       "44  [-93.8691, 42.4392]         Point  EBS                  IA8806   \n",
       "\n",
       "   properties.country properties.county  properties.elevation  \\\n",
       "0                  US           Kossuth                 368.8   \n",
       "1                  US              Polk                 270.7   \n",
       "2                  US              Cass                 351.7   \n",
       "3                  US           Audubon                 399.3   \n",
       "4                  US             Boone                 349.3   \n",
       "..                ...               ...                   ...   \n",
       "40                 US           Fremont                 296.0   \n",
       "41                 US       Buena Vista                 449.9   \n",
       "42                 US            Benton                 255.0   \n",
       "43                 US        Washington                 228.9   \n",
       "44                 US          Hamilton                 337.4   \n",
       "\n",
       "   properties.ncdc81 properties.sid properties.sname properties.state  \\\n",
       "0        USC00130133            AXA           ALGONA               IA   \n",
       "1        USC00130241            IKV           ANKENY               IA   \n",
       "2        USC00130364            AIO         ATLANTIC               IA   \n",
       "3        USC00130385            ADU          AUDUBON               IA   \n",
       "4        USC00130807            BNW       BOONE MUNI               IA   \n",
       "..               ...            ...              ...              ...   \n",
       "40       USC00137613            SDA  SHENANDOAH MUNI               IA   \n",
       "41       USC00137979            SLB       Storm Lake               IA   \n",
       "42       USC00138568            VTI           VINTON               IA   \n",
       "43       USC00138688            AWG       WASHINGTON               IA   \n",
       "44       USC00138806            EBS     Webster City               IA   \n",
       "\n",
       "   properties.tzname properties.ugc_county properties.ugc_zone properties.wfo  \\\n",
       "0    America/Chicago                IAC109              IAZ005            DMX   \n",
       "1    America/Chicago                IAC153              IAZ060            DMX   \n",
       "2    America/Chicago                IAC029              IAZ070            DMX   \n",
       "3    America/Chicago                IAC009              IAZ057            DMX   \n",
       "4    America/Chicago                IAC015              IAZ047            DMX   \n",
       "..               ...                   ...                 ...            ...   \n",
       "40   America/Chicago                IAC071              IAZ090            OAX   \n",
       "41   America/Chicago                IAC021              IAZ301            FSD   \n",
       "42   America/Chicago                IAC011              IAZ051            DVN   \n",
       "43   America/Chicago                IAC183              IAZ077            DVN   \n",
       "44   America/Chicago                IAC079              IAZ036            DMX   \n",
       "\n",
       "       type  \n",
       "0   Feature  \n",
       "1   Feature  \n",
       "2   Feature  \n",
       "3   Feature  \n",
       "4   Feature  \n",
       "..      ...  \n",
       "40  Feature  \n",
       "41  Feature  \n",
       "42  Feature  \n",
       "43  Feature  \n",
       "44  Feature  \n",
       "\n",
       "[45 rows x 16 columns]"
      ]
     },
     "execution_count": 112,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.io.json.json_normalize(js['features'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sure, it's not *that* difficult to write a quick for loop or list comprehension to extract those,\n",
    "but that gets tedious.\n",
    "If we were using the latitude and longitude data, we would want to split\n",
    "the `geometry.coordinates` column into two. But we aren't so we won't.\n",
    "\n",
    "Going back to the task, we get the airport IDs for every network (state)\n",
    "with `get_ids`. Then we pass those IDs into `get_weather` to fetch the\n",
    "actual weather data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 117,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "ids = pd.concat([get_ids(network) for network in networks], ignore_index=True)\n",
    "gr = ids.groupby('network')\n",
    "\n",
    "store = 'data/weather.h5'\n",
    "\n",
    "if not os.path.exists(store):\n",
    "    os.makedirs(\"data/weather\", exist_ok=True)\n",
    "\n",
    "    for k, v in gr:\n",
    "        weather = get_weather(v['id'])\n",
    "        weather.to_csv(\"data/weather/{}.csv\".format(k))\n",
    "\n",
    "    weather = pd.concat([\n",
    "        pd.read_csv(f, parse_dates=['date'], index_col=['station', 'date'])\n",
    "        for f in glob.glob('data/weather/*.csv')\n",
    "    ]).sort_index()\n",
    "\n",
    "    weather.to_hdf(\"data/weather.h5\", \"weather\")\n",
    "else:\n",
    "    weather = pd.read_hdf(\"data/weather.h5\", \"weather\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "weather.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "OK, that was a bit of work. Here's a plot to reward ourselves."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<seaborn.axisgrid.FacetGrid at 0x11e9917f0>"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x11e991320>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "airports = ['W43', 'AFO', '82V', 'DUB']\n",
    "\n",
    "g = sns.FacetGrid(weather.loc[airports].reset_index(),\n",
    "                  col='station', hue='station', col_wrap=2, size=4)\n",
    "g.map(sns.regplot, 'sped', 'gust_mph')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Set Operations\n",
    "\n",
    "Indexes are set-like (technically *multi*sets, since you can have duplicates), so they support most python `set` operations. Since indexes are immutable you won't find any of the inplace `set` operations.\n",
    "One other difference is that since `Index`es are also array-like, you can't use some infix operators like `-` for `difference`. If you have a numeric index it is unclear whether you intend to perform math operations or set operations.\n",
    "You can use `&` for intersection, `|` for union, and `^` for symmetric difference though, since there's no ambiguity.\n",
    "\n",
    "For example, lets find the set of airports that we have both weather and flight information on. Since `weather` had a MultiIndex of `airport, datetime`, we'll use the `levels` attribute to get at the airport data, separate from the date data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Index(['ABE', 'ABI', 'ABQ', 'ABR', 'ABY', 'ACT', 'ACV', 'ACY', 'AEX', 'AGS',\n",
       "       ...\n",
       "       'TUL', 'TUS', 'TVC', 'TWF', 'TXK', 'TYR', 'TYS', 'VLD', 'VPS', 'XNA'],\n",
       "      dtype='object', length=265)"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Bring in the flights data\n",
    "\n",
    "flights = pd.read_hdf('data/flights.h5', 'flights')\n",
    "\n",
    "weather_locs = weather.index.levels[0]\n",
    "# The `categories` attribute of a Categorical is an Index\n",
    "origin_locs = flights.origin.cat.categories\n",
    "dest_locs = flights.dest.cat.categories\n",
    "\n",
    "airports = weather_locs & origin_locs & dest_locs\n",
    "airports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Weather, no flights:\n",
      "\t Index(['01M', '04V', '04W', '05U', '06D', '08D', '0A9', '0CO', '0E0', '0F2',\n",
      "       ...\n",
      "       'Y50', 'Y51', 'Y63', 'Y70', 'YIP', 'YKM', 'YKN', 'YNG', 'ZPH', 'ZZV'],\n",
      "      dtype='object', length=1910)\n",
      "\n",
      "Flights, no weather:\n",
      "\t Index(['ADK', 'ADQ', 'ANC', 'BET', 'BQN', 'BRW', 'CDV', 'FAI', 'FCA', 'GUM',\n",
      "       'HNL', 'ITO', 'JNU', 'KOA', 'KTN', 'LIH', 'MQT', 'OGG', 'OME', 'OTZ',\n",
      "       'PPG', 'PSE', 'PSG', 'SCC', 'SCE', 'SIT', 'SJU', 'STT', 'STX', 'WRG',\n",
      "       'YAK', 'YUM'],\n",
      "      dtype='object')\n",
      "\n",
      "Dropped Stations:\n",
      "\t Index(['01M', '04V', '04W', '05U', '06D', '08D', '0A9', '0CO', '0E0', '0F2',\n",
      "       ...\n",
      "       'Y63', 'Y70', 'YAK', 'YIP', 'YKM', 'YKN', 'YNG', 'YUM', 'ZPH', 'ZZV'],\n",
      "      dtype='object', length=1942)\n"
     ]
    }
   ],
   "source": [
    "print(\"Weather, no flights:\\n\\t\", weather_locs.difference(origin_locs | dest_locs), end='\\n\\n')\n",
    "\n",
    "print(\"Flights, no weather:\\n\\t\", (origin_locs | dest_locs).difference(weather_locs), end='\\n\\n')\n",
    "\n",
    "print(\"Dropped Stations:\\n\\t\", (origin_locs | dest_locs) ^ weather_locs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Flavors\n",
    "\n",
    "Pandas has many subclasses of the regular `Index`, each tailored to a specific kind of data.\n",
    "Most of the time these will be created for you automatically, so you don't have to worry about which one to choose.\n",
    "\n",
    "1. [`Index`](http://pandas.pydata.org/pandas-docs/version/0.18.0/generated/pandas.Index.html#pandas.Index)\n",
    "2. `Int64Index`\n",
    "3. `RangeIndex`: Memory-saving special case of `Int64Index`\n",
    "4. `FloatIndex`\n",
    "5. `DatetimeIndex`: Datetime64[ns] precision data\n",
    "6. `PeriodIndex`: Regularly-spaced, arbitrary precision datetime data.\n",
    "7. `TimedeltaIndex`\n",
    "8. `CategoricalIndex`\n",
    "9. `MultiIndex`\n",
    "\n",
    "You will sometimes create a `DatetimeIndex` with [`pd.date_range`](http://pandas.pydata.org/pandas-docs/version/0.18.0/generated/pandas.date_range.html) ([`pd.period_range`](http://pandas.pydata.org/pandas-docs/version/0.18.0/generated/pandas.period_range.html) for `PeriodIndex`).\n",
    "And you'll sometimes make a `MultiIndex` directly too (I'll have an example of this in my post on performace).\n",
    "\n",
    "Some of these specialized index types are purely optimizations; others use information about the data to provide additional methods.\n",
    "And while you might occasionally work with indexes directly (like the set operations above), most of they time you'll be operating on a Series or DataFrame, which in turn makes use of its Index.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Row Slicing\n",
    "We saw in part one that they're great for making *row* subsetting as easy as column subsetting."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>tmpf</th>\n",
       "      <th>relh</th>\n",
       "      <th>sped</th>\n",
       "      <th>mslp</th>\n",
       "      <th>p01i</th>\n",
       "      <th>vsby</th>\n",
       "      <th>gust_mph</th>\n",
       "      <th>skyc1</th>\n",
       "      <th>skyc2</th>\n",
       "      <th>skyc3</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2014-01-01 00:54:00</th>\n",
       "      <td>10.94</td>\n",
       "      <td>72.79</td>\n",
       "      <td>10.4</td>\n",
       "      <td>1024.9</td>\n",
       "      <td>0.0</td>\n",
       "      <td>10.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>FEW</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 01:54:00</th>\n",
       "      <td>10.94</td>\n",
       "      <td>72.79</td>\n",
       "      <td>11.5</td>\n",
       "      <td>1025.4</td>\n",
       "      <td>0.0</td>\n",
       "      <td>10.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>OVC</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 02:54:00</th>\n",
       "      <td>10.94</td>\n",
       "      <td>72.79</td>\n",
       "      <td>8.1</td>\n",
       "      <td>1025.3</td>\n",
       "      <td>0.0</td>\n",
       "      <td>10.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>BKN</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 03:54:00</th>\n",
       "      <td>10.94</td>\n",
       "      <td>72.79</td>\n",
       "      <td>9.2</td>\n",
       "      <td>1025.3</td>\n",
       "      <td>0.0</td>\n",
       "      <td>10.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>OVC</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 04:54:00</th>\n",
       "      <td>10.04</td>\n",
       "      <td>72.69</td>\n",
       "      <td>9.2</td>\n",
       "      <td>1024.7</td>\n",
       "      <td>0.0</td>\n",
       "      <td>10.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>BKN</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                      tmpf   relh  sped    mslp  p01i  vsby  gust_mph skyc1  \\\n",
       "date                                                                          \n",
       "2014-01-01 00:54:00  10.94  72.79  10.4  1024.9   0.0  10.0       NaN   FEW   \n",
       "2014-01-01 01:54:00  10.94  72.79  11.5  1025.4   0.0  10.0       NaN   OVC   \n",
       "2014-01-01 02:54:00  10.94  72.79   8.1  1025.3   0.0  10.0       NaN   BKN   \n",
       "2014-01-01 03:54:00  10.94  72.79   9.2  1025.3   0.0  10.0       NaN   OVC   \n",
       "2014-01-01 04:54:00  10.04  72.69   9.2  1024.7   0.0  10.0       NaN   BKN   \n",
       "\n",
       "                    skyc2 skyc3  \n",
       "date                             \n",
       "2014-01-01 00:54:00     M     M  \n",
       "2014-01-01 01:54:00     M     M  \n",
       "2014-01-01 02:54:00     M     M  \n",
       "2014-01-01 03:54:00     M     M  \n",
       "2014-01-01 04:54:00     M     M  "
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "weather.loc['DSM'].head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Without indexes we'd probably resort to boolean masks."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>station</th>\n",
       "      <th>date</th>\n",
       "      <th>tmpf</th>\n",
       "      <th>relh</th>\n",
       "      <th>sped</th>\n",
       "      <th>mslp</th>\n",
       "      <th>p01i</th>\n",
       "      <th>vsby</th>\n",
       "      <th>gust_mph</th>\n",
       "      <th>skyc1</th>\n",
       "      <th>skyc2</th>\n",
       "      <th>skyc3</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>884855</th>\n",
       "      <td>DSM</td>\n",
       "      <td>2014-01-01 00:54:00</td>\n",
       "      <td>10.94</td>\n",
       "      <td>72.79</td>\n",
       "      <td>10.4</td>\n",
       "      <td>1024.9</td>\n",
       "      <td>0.0</td>\n",
       "      <td>10.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>FEW</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>884856</th>\n",
       "      <td>DSM</td>\n",
       "      <td>2014-01-01 01:54:00</td>\n",
       "      <td>10.94</td>\n",
       "      <td>72.79</td>\n",
       "      <td>11.5</td>\n",
       "      <td>1025.4</td>\n",
       "      <td>0.0</td>\n",
       "      <td>10.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>OVC</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>884857</th>\n",
       "      <td>DSM</td>\n",
       "      <td>2014-01-01 02:54:00</td>\n",
       "      <td>10.94</td>\n",
       "      <td>72.79</td>\n",
       "      <td>8.1</td>\n",
       "      <td>1025.3</td>\n",
       "      <td>0.0</td>\n",
       "      <td>10.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>BKN</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>884858</th>\n",
       "      <td>DSM</td>\n",
       "      <td>2014-01-01 03:54:00</td>\n",
       "      <td>10.94</td>\n",
       "      <td>72.79</td>\n",
       "      <td>9.2</td>\n",
       "      <td>1025.3</td>\n",
       "      <td>0.0</td>\n",
       "      <td>10.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>OVC</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>884859</th>\n",
       "      <td>DSM</td>\n",
       "      <td>2014-01-01 04:54:00</td>\n",
       "      <td>10.04</td>\n",
       "      <td>72.69</td>\n",
       "      <td>9.2</td>\n",
       "      <td>1024.7</td>\n",
       "      <td>0.0</td>\n",
       "      <td>10.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>BKN</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       station                date   tmpf   relh  sped    mslp  p01i  vsby  \\\n",
       "884855     DSM 2014-01-01 00:54:00  10.94  72.79  10.4  1024.9   0.0  10.0   \n",
       "884856     DSM 2014-01-01 01:54:00  10.94  72.79  11.5  1025.4   0.0  10.0   \n",
       "884857     DSM 2014-01-01 02:54:00  10.94  72.79   8.1  1025.3   0.0  10.0   \n",
       "884858     DSM 2014-01-01 03:54:00  10.94  72.79   9.2  1025.3   0.0  10.0   \n",
       "884859     DSM 2014-01-01 04:54:00  10.04  72.69   9.2  1024.7   0.0  10.0   \n",
       "\n",
       "        gust_mph skyc1 skyc2 skyc3  \n",
       "884855       NaN   FEW     M     M  \n",
       "884856       NaN   OVC     M     M  \n",
       "884857       NaN   BKN     M     M  \n",
       "884858       NaN   OVC     M     M  \n",
       "884859       NaN   BKN     M     M  "
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "weather2 = weather.reset_index()\n",
    "weather2[weather2['station'] == 'DSM'].head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Slightly less convenient, but still doable."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Indexes for Easier Arithmetic, Analysis"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It's nice to have your metadata (labels on each observation) next to you actual values. But if you store them in an array, they'll get in the way of your operations.\n",
    "Say we wanted to translate the Fahrenheit temperature to Celsius."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>tmpf</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>station</th>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"5\" valign=\"top\">01M</th>\n",
       "      <th>2014-01-01 00:15:00</th>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 00:35:00</th>\n",
       "      <td>0.8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 00:55:00</th>\n",
       "      <td>0.3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 01:15:00</th>\n",
       "      <td>-0.1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 01:35:00</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"5\" valign=\"top\">ZZV</th>\n",
       "      <th>2014-01-30 19:53:00</th>\n",
       "      <td>-2.8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-30 20:53:00</th>\n",
       "      <td>-2.2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-30 21:53:00</th>\n",
       "      <td>-2.2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-30 22:53:00</th>\n",
       "      <td>-2.8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-30 23:53:00</th>\n",
       "      <td>-1.7</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>3303647 rows × 1 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                             tmpf\n",
       "station date                     \n",
       "01M     2014-01-01 00:15:00   1.0\n",
       "        2014-01-01 00:35:00   0.8\n",
       "        2014-01-01 00:55:00   0.3\n",
       "        2014-01-01 01:15:00  -0.1\n",
       "        2014-01-01 01:35:00   0.0\n",
       "...                           ...\n",
       "ZZV     2014-01-30 19:53:00  -2.8\n",
       "        2014-01-30 20:53:00  -2.2\n",
       "        2014-01-30 21:53:00  -2.2\n",
       "        2014-01-30 22:53:00  -2.8\n",
       "        2014-01-30 23:53:00  -1.7\n",
       "\n",
       "[3303647 rows x 1 columns]"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# With indecies\n",
    "temp = weather['tmpf']\n",
    "\n",
    "c = (temp - 32) * 5 / 9\n",
    "c.to_frame()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>station</th>\n",
       "      <th>date</th>\n",
       "      <th>tmpf</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>01M</td>\n",
       "      <td>2014-01-01 00:15:00</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>01M</td>\n",
       "      <td>2014-01-01 00:35:00</td>\n",
       "      <td>0.8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>01M</td>\n",
       "      <td>2014-01-01 00:55:00</td>\n",
       "      <td>0.3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>01M</td>\n",
       "      <td>2014-01-01 01:15:00</td>\n",
       "      <td>-0.1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>01M</td>\n",
       "      <td>2014-01-01 01:35:00</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  station                date  tmpf\n",
       "0     01M 2014-01-01 00:15:00   1.0\n",
       "1     01M 2014-01-01 00:35:00   0.8\n",
       "2     01M 2014-01-01 00:55:00   0.3\n",
       "3     01M 2014-01-01 01:15:00  -0.1\n",
       "4     01M 2014-01-01 01:35:00   0.0"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# without\n",
    "temp2 = weather.reset_index()[['station', 'date', 'tmpf']]\n",
    "\n",
    "temp2['tmpf'] = (temp2['tmpf'] - 32) * 5 / 9\n",
    "temp2.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Again, not terrible, but not as good.\n",
    "And, what if you had wanted to keep Fahrenheit around as well, instead of overwriting it like we did?\n",
    "Then you'd need to make a copy of everything, including the `station` and `date` columns.\n",
    "We don't have that problem, since indexes are immutable and safely shared between DataFrames / Series."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "temp.index is c.index"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Indexes for Alignment\n",
    "\n",
    "I've saved the best for last.\n",
    "Automatic alignment, or reindexing, is fundamental to pandas.\n",
    "\n",
    "All binary operations (add, multiply, etc.) between Series/DataFrames first *align* and then proceed.\n",
    "\n",
    "Let's suppose we have hourly observations on temperature and windspeed.\n",
    "And suppose some of the observations were invalid, and not reported (simulated below by sampling from the full dataset). We'll assume the missing windspeed observations were potentially different from the missing temperature observations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [],
   "source": [
    "dsm = weather.loc['DSM']\n",
    "\n",
    "hourly = dsm.resample('H').mean()\n",
    "\n",
    "temp = hourly['tmpf'].sample(frac=.5, random_state=1).sort_index()\n",
    "sped = hourly['sped'].sample(frac=.5, random_state=2).sort_index()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>tmpf</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2014-01-01 00:00:00</th>\n",
       "      <td>10.94</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 02:00:00</th>\n",
       "      <td>10.94</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 03:00:00</th>\n",
       "      <td>10.94</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 04:00:00</th>\n",
       "      <td>10.04</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 05:00:00</th>\n",
       "      <td>10.04</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                      tmpf\n",
       "date                      \n",
       "2014-01-01 00:00:00  10.94\n",
       "2014-01-01 02:00:00  10.94\n",
       "2014-01-01 03:00:00  10.94\n",
       "2014-01-01 04:00:00  10.04\n",
       "2014-01-01 05:00:00  10.04"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "temp.head().to_frame()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "date\n",
       "2014-01-01 01:00:00    11.5\n",
       "2014-01-01 02:00:00     8.1\n",
       "2014-01-01 03:00:00     9.2\n",
       "2014-01-01 04:00:00     9.2\n",
       "2014-01-01 05:00:00    10.4\n",
       "Name: sped, dtype: float64"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sped.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice that the two indexes aren't identical.\n",
    "\n",
    "Suppose that the `windspeed : temperature` ratio is meaningful.\n",
    "When we go to compute that, pandas will automatically align the two by index label."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "date\n",
       "2014-01-01 00:00:00         NaN\n",
       "2014-01-01 01:00:00         NaN\n",
       "2014-01-01 02:00:00    0.740402\n",
       "2014-01-01 03:00:00    0.840951\n",
       "2014-01-01 04:00:00    0.916335\n",
       "                         ...   \n",
       "2014-01-30 13:00:00         NaN\n",
       "2014-01-30 14:00:00    0.590416\n",
       "2014-01-30 17:00:00         NaN\n",
       "2014-01-30 21:00:00         NaN\n",
       "2014-01-30 23:00:00         NaN\n",
       "Length: 550, dtype: float64"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sped / temp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This lets you focus on doing the operation, rather than manually aligning things, ensuring that the arrays are the same length and in the same order.\n",
    "By deault, missing values are inserted where the two don't align.\n",
    "You can use the method version of any binary operation to specify a `fill_value`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "date\n",
       "2014-01-01 00:00:00     0.091408\n",
       "2014-01-01 01:00:00    11.500000\n",
       "2014-01-01 02:00:00     0.740402\n",
       "2014-01-01 03:00:00     0.840951\n",
       "2014-01-01 04:00:00     0.916335\n",
       "                         ...    \n",
       "2014-01-30 13:00:00     0.027809\n",
       "2014-01-30 14:00:00     0.590416\n",
       "2014-01-30 17:00:00     0.023267\n",
       "2014-01-30 21:00:00     0.035663\n",
       "2014-01-30 23:00:00    13.800000\n",
       "Length: 550, dtype: float64"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sped.div(temp, fill_value=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And since I couldn't find anywhere else to put it, you can control the axis the operation is aligned along as well."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>tmpf</th>\n",
       "      <th>relh</th>\n",
       "      <th>sped</th>\n",
       "      <th>mslp</th>\n",
       "      <th>p01i</th>\n",
       "      <th>vsby</th>\n",
       "      <th>gust_mph</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2014-01-01 00:00:00</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 01:00:00</th>\n",
       "      <td>0.951304</td>\n",
       "      <td>6.329565</td>\n",
       "      <td>1.0</td>\n",
       "      <td>89.165217</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.869565</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 02:00:00</th>\n",
       "      <td>1.350617</td>\n",
       "      <td>8.986420</td>\n",
       "      <td>1.0</td>\n",
       "      <td>126.580247</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.234568</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 03:00:00</th>\n",
       "      <td>1.189130</td>\n",
       "      <td>7.911957</td>\n",
       "      <td>1.0</td>\n",
       "      <td>111.445652</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.086957</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 04:00:00</th>\n",
       "      <td>1.091304</td>\n",
       "      <td>7.901087</td>\n",
       "      <td>1.0</td>\n",
       "      <td>111.380435</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.086957</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-30 19:00:00</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-30 20:00:00</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-30 21:00:00</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-30 22:00:00</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-30 23:00:00</th>\n",
       "      <td>1.588406</td>\n",
       "      <td>4.502174</td>\n",
       "      <td>1.0</td>\n",
       "      <td>73.434783</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.724638</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>720 rows × 7 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                         tmpf      relh  sped        mslp  p01i      vsby  \\\n",
       "date                                                                        \n",
       "2014-01-01 00:00:00       NaN       NaN   NaN         NaN   NaN       NaN   \n",
       "2014-01-01 01:00:00  0.951304  6.329565   1.0   89.165217   0.0  0.869565   \n",
       "2014-01-01 02:00:00  1.350617  8.986420   1.0  126.580247   0.0  1.234568   \n",
       "2014-01-01 03:00:00  1.189130  7.911957   1.0  111.445652   0.0  1.086957   \n",
       "2014-01-01 04:00:00  1.091304  7.901087   1.0  111.380435   0.0  1.086957   \n",
       "...                       ...       ...   ...         ...   ...       ...   \n",
       "2014-01-30 19:00:00       NaN       NaN   NaN         NaN   NaN       NaN   \n",
       "2014-01-30 20:00:00       NaN       NaN   NaN         NaN   NaN       NaN   \n",
       "2014-01-30 21:00:00       NaN       NaN   NaN         NaN   NaN       NaN   \n",
       "2014-01-30 22:00:00       NaN       NaN   NaN         NaN   NaN       NaN   \n",
       "2014-01-30 23:00:00  1.588406  4.502174   1.0   73.434783   0.0  0.724638   \n",
       "\n",
       "                     gust_mph  \n",
       "date                           \n",
       "2014-01-01 00:00:00       NaN  \n",
       "2014-01-01 01:00:00       NaN  \n",
       "2014-01-01 02:00:00       NaN  \n",
       "2014-01-01 03:00:00       NaN  \n",
       "2014-01-01 04:00:00       NaN  \n",
       "...                       ...  \n",
       "2014-01-30 19:00:00       NaN  \n",
       "2014-01-30 20:00:00       NaN  \n",
       "2014-01-30 21:00:00       NaN  \n",
       "2014-01-30 22:00:00       NaN  \n",
       "2014-01-30 23:00:00       NaN  \n",
       "\n",
       "[720 rows x 7 columns]"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "hourly.div(sped, axis='index')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The non row-labeled version of this is messy."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\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>0</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2014-01-01 02:00:00</td>\n",
       "      <td>0.740402</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2014-01-01 03:00:00</td>\n",
       "      <td>0.840951</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2014-01-01 04:00:00</td>\n",
       "      <td>0.916335</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2014-01-01 05:00:00</td>\n",
       "      <td>1.035857</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>2014-01-01 13:00:00</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>351</th>\n",
       "      <td>2014-01-29 23:00:00</td>\n",
       "      <td>0.541495</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>354</th>\n",
       "      <td>2014-01-30 05:00:00</td>\n",
       "      <td>0.493440</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>356</th>\n",
       "      <td>2014-01-30 09:00:00</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>357</th>\n",
       "      <td>2014-01-30 10:00:00</td>\n",
       "      <td>0.624643</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>358</th>\n",
       "      <td>2014-01-30 14:00:00</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>170 rows × 2 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                   date         0\n",
       "1   2014-01-01 02:00:00  0.740402\n",
       "2   2014-01-01 03:00:00  0.840951\n",
       "3   2014-01-01 04:00:00  0.916335\n",
       "4   2014-01-01 05:00:00  1.035857\n",
       "8   2014-01-01 13:00:00       NaN\n",
       "..                  ...       ...\n",
       "351 2014-01-29 23:00:00  0.541495\n",
       "354 2014-01-30 05:00:00  0.493440\n",
       "356 2014-01-30 09:00:00       NaN\n",
       "357 2014-01-30 10:00:00  0.624643\n",
       "358 2014-01-30 14:00:00       NaN\n",
       "\n",
       "[170 rows x 2 columns]"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "temp2 = temp.reset_index()\n",
    "sped2 = sped.reset_index()\n",
    "\n",
    "# Find rows where the operation is defined\n",
    "common_dates = pd.Index(temp2.date) & sped2.date\n",
    "pd.concat([\n",
    "    # concat to not lose date information\n",
    "    sped2.loc[sped2['date'].isin(common_dates), 'date'],\n",
    "    (sped2.loc[sped2.date.isin(common_dates), 'sped'] /\n",
    "     temp2.loc[temp2.date.isin(common_dates), 'tmpf'])],\n",
    "    axis=1).dropna(how='all')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And we have a bug in there. Can you spot it?\n",
    "I only grabbed the dates from `sped2` in the line `sped2.loc[sped2['date'].isin(common_dates), 'date']`.\n",
    "Really that should be `sped2.loc[sped2.date.isin(common_dates)] | temp2.loc[temp2.date.isin(common_dates)]`.\n",
    "But I think leaving the buggy version states my case even more strongly. The `temp / sped` version where pandas aligns everything is better."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Merging\n",
    "\n",
    "There are two ways of merging DataFrames / Series in pandas.\n",
    "\n",
    "1. Relational Database style with `pd.merge`\n",
    "2. Array style with `pd.concat`\n",
    "\n",
    "Personally, I think in terms of the `concat` style.\n",
    "I learned pandas before I ever really used SQL, so it comes more naturally to me I suppose.\n",
    "\n",
    "### Concat Version"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>tmpf</th>\n",
       "      <th>sped</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2014-01-01 00:00:00</th>\n",
       "      <td>10.94</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 01:00:00</th>\n",
       "      <td>NaN</td>\n",
       "      <td>11.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 02:00:00</th>\n",
       "      <td>10.94</td>\n",
       "      <td>8.1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 03:00:00</th>\n",
       "      <td>10.94</td>\n",
       "      <td>9.2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 04:00:00</th>\n",
       "      <td>10.04</td>\n",
       "      <td>9.2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                      tmpf  sped\n",
       "date                            \n",
       "2014-01-01 00:00:00  10.94   NaN\n",
       "2014-01-01 01:00:00    NaN  11.5\n",
       "2014-01-01 02:00:00  10.94   8.1\n",
       "2014-01-01 03:00:00  10.94   9.2\n",
       "2014-01-01 04:00:00  10.04   9.2"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.concat([temp, sped], axis=1).head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `axis` parameter controls how the data should be stacked, `0` for vertically, `1` for horizontally.\n",
    "The `join` parameter controls the merge behavior on the shared axis, (the Index for `axis=1`). By default it's like a union of the two indexes, or an outer join."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>tmpf</th>\n",
       "      <th>sped</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2014-01-01 02:00:00</th>\n",
       "      <td>10.94</td>\n",
       "      <td>8.100</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 03:00:00</th>\n",
       "      <td>10.94</td>\n",
       "      <td>9.200</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 04:00:00</th>\n",
       "      <td>10.04</td>\n",
       "      <td>9.200</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 05:00:00</th>\n",
       "      <td>10.04</td>\n",
       "      <td>10.400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 13:00:00</th>\n",
       "      <td>8.96</td>\n",
       "      <td>13.825</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-29 23:00:00</th>\n",
       "      <td>35.96</td>\n",
       "      <td>18.400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-30 05:00:00</th>\n",
       "      <td>33.98</td>\n",
       "      <td>17.300</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-30 09:00:00</th>\n",
       "      <td>35.06</td>\n",
       "      <td>16.100</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-30 10:00:00</th>\n",
       "      <td>35.06</td>\n",
       "      <td>21.900</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-30 14:00:00</th>\n",
       "      <td>35.06</td>\n",
       "      <td>20.700</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>170 rows × 2 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                      tmpf    sped\n",
       "date                              \n",
       "2014-01-01 02:00:00  10.94   8.100\n",
       "2014-01-01 03:00:00  10.94   9.200\n",
       "2014-01-01 04:00:00  10.04   9.200\n",
       "2014-01-01 05:00:00  10.04  10.400\n",
       "2014-01-01 13:00:00   8.96  13.825\n",
       "...                    ...     ...\n",
       "2014-01-29 23:00:00  35.96  18.400\n",
       "2014-01-30 05:00:00  33.98  17.300\n",
       "2014-01-30 09:00:00  35.06  16.100\n",
       "2014-01-30 10:00:00  35.06  21.900\n",
       "2014-01-30 14:00:00  35.06  20.700\n",
       "\n",
       "[170 rows x 2 columns]"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.concat([temp, sped], axis=1, join='inner')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Merge Version\n",
    "\n",
    "Since we're joining by index here the merge version is quite similar.\n",
    "We'll see an example later of a one-to-many join where the two differ."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>tmpf</th>\n",
       "      <th>sped</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2014-01-01 02:00:00</th>\n",
       "      <td>10.94</td>\n",
       "      <td>8.100</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 03:00:00</th>\n",
       "      <td>10.94</td>\n",
       "      <td>9.200</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 04:00:00</th>\n",
       "      <td>10.04</td>\n",
       "      <td>9.200</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 05:00:00</th>\n",
       "      <td>10.04</td>\n",
       "      <td>10.400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 13:00:00</th>\n",
       "      <td>8.96</td>\n",
       "      <td>13.825</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                      tmpf    sped\n",
       "date                              \n",
       "2014-01-01 02:00:00  10.94   8.100\n",
       "2014-01-01 03:00:00  10.94   9.200\n",
       "2014-01-01 04:00:00  10.04   9.200\n",
       "2014-01-01 05:00:00  10.04  10.400\n",
       "2014-01-01 13:00:00   8.96  13.825"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.merge(temp.to_frame(), sped.to_frame(), left_index=True, right_index=True).head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>tmpf</th>\n",
       "      <th>sped</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2014-01-01 00:00:00</th>\n",
       "      <td>10.94</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 01:00:00</th>\n",
       "      <td>NaN</td>\n",
       "      <td>11.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 02:00:00</th>\n",
       "      <td>10.94</td>\n",
       "      <td>8.1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 03:00:00</th>\n",
       "      <td>10.94</td>\n",
       "      <td>9.2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2014-01-01 04:00:00</th>\n",
       "      <td>10.04</td>\n",
       "      <td>9.2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                      tmpf  sped\n",
       "date                            \n",
       "2014-01-01 00:00:00  10.94   NaN\n",
       "2014-01-01 01:00:00    NaN  11.5\n",
       "2014-01-01 02:00:00  10.94   8.1\n",
       "2014-01-01 03:00:00  10.94   9.2\n",
       "2014-01-01 04:00:00  10.04   9.2"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.merge(temp.to_frame(), sped.to_frame(), left_index=True, right_index=True,\n",
    "         how='outer').head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Like I said, I typically prefer `concat` to `merge`.\n",
    "The exception here is one-to-many type joins. Let's walk through one of those,\n",
    "where we join the flight data to the weather data.\n",
    "To focus just on the merge, we'll aggregate hour weather data to be daily, rather than trying to find the closest recorded weather observation to each departure (you could do that, but it's not the focus right now). We'll then join the one `(airport, date)` record to the many `(airport, date, flight)` records.\n",
    "\n",
    "Quick tangent, to get the weather data to daily frequency, we'll need to resample (more on that in the timeseries section). The resample essentially splits the recorded values into daily buckets and computes the aggregation function on each bucket. The only wrinkle is that we have to resample *by station*, so we'll use the `pd.TimeGrouper` helper."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [],
   "source": [
    "idx_cols = ['unique_carrier', 'origin', 'dest', 'tail_num', 'fl_num', 'fl_date']\n",
    "data_cols = ['crs_dep_time', 'dep_delay', 'crs_arr_time', 'arr_delay',\n",
    "             'taxi_out', 'taxi_in', 'wheels_off', 'wheels_on']\n",
    "\n",
    "df = flights.set_index(idx_cols)[data_cols].sort_index()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>tmpf</th>\n",
       "      <th>relh</th>\n",
       "      <th>sped</th>\n",
       "      <th>mslp</th>\n",
       "      <th>p01i</th>\n",
       "      <th>vsby</th>\n",
       "      <th>gust_mph</th>\n",
       "      <th>skyc1</th>\n",
       "      <th>skyc2</th>\n",
       "      <th>skyc3</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th>station</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"5\" valign=\"top\">2014-01-01</th>\n",
       "      <th>01M</th>\n",
       "      <td>35.747500</td>\n",
       "      <td>81.117917</td>\n",
       "      <td>2.294444</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "      <td>9.229167</td>\n",
       "      <td>NaN</td>\n",
       "      <td>CLR</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>04V</th>\n",
       "      <td>18.350000</td>\n",
       "      <td>72.697778</td>\n",
       "      <td>11.250000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "      <td>9.861111</td>\n",
       "      <td>31.603571</td>\n",
       "      <td>CLR</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>04W</th>\n",
       "      <td>-9.075000</td>\n",
       "      <td>69.908056</td>\n",
       "      <td>3.647222</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>OVC</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>05U</th>\n",
       "      <td>26.321127</td>\n",
       "      <td>71.519859</td>\n",
       "      <td>3.829577</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "      <td>9.929577</td>\n",
       "      <td>NaN</td>\n",
       "      <td>CLR</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>06D</th>\n",
       "      <td>-11.388060</td>\n",
       "      <td>73.784179</td>\n",
       "      <td>5.359722</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "      <td>9.576389</td>\n",
       "      <td>NaN</td>\n",
       "      <td>CLR</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                         tmpf       relh       sped  mslp  p01i       vsby  \\\n",
       "date       station                                                           \n",
       "2014-01-01 01M      35.747500  81.117917   2.294444   NaN   0.0   9.229167   \n",
       "           04V      18.350000  72.697778  11.250000   NaN   0.0   9.861111   \n",
       "           04W      -9.075000  69.908056   3.647222   NaN   0.0  10.000000   \n",
       "           05U      26.321127  71.519859   3.829577   NaN   0.0   9.929577   \n",
       "           06D     -11.388060  73.784179   5.359722   NaN   0.0   9.576389   \n",
       "\n",
       "                     gust_mph skyc1 skyc2 skyc3  \n",
       "date       station                               \n",
       "2014-01-01 01M            NaN   CLR     M     M  \n",
       "           04V      31.603571   CLR     M     M  \n",
       "           04W            NaN   OVC     M     M  \n",
       "           05U            NaN   CLR     M     M  \n",
       "           06D            NaN   CLR     M     M  "
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def mode(x):\n",
    "    '''\n",
    "    Arbitrarily break ties.\n",
    "    '''\n",
    "    return x.value_counts().index[0]\n",
    "\n",
    "aggfuncs = {'tmpf': 'mean', 'relh': 'mean',\n",
    "            'sped': 'mean', 'mslp': 'mean',\n",
    "            'p01i': 'mean', 'vsby': 'mean',\n",
    "            'gust_mph': 'mean', 'skyc1': mode,\n",
    "            'skyc2': mode, 'skyc3': mode}\n",
    "# TimeGrouper works on a DatetimeIndex, so we move `station` to the\n",
    "# columns and then groupby it as well.\n",
    "daily = (weather.reset_index(level=\"station\")\n",
    "                .groupby([pd.TimeGrouper('1d'), \"station\"])\n",
    "                .agg(aggfuncs))\n",
    "\n",
    "daily.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that we have daily flight and weather data, we can merge.\n",
    "We'll use the `on` keyword to indicate the columns we'll merge on (this is like a `USING (...)` SQL statement), we just have to make sure the names align."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['2017-01-01T00:00:00.000000000', '2017-01-02T00:00:00.000000000',\n",
       "       '2017-01-03T00:00:00.000000000', '2017-01-04T00:00:00.000000000',\n",
       "       '2017-01-05T00:00:00.000000000', '2017-01-06T00:00:00.000000000',\n",
       "       '2017-01-07T00:00:00.000000000', '2017-01-08T00:00:00.000000000',\n",
       "       '2017-01-09T00:00:00.000000000', '2017-01-10T00:00:00.000000000',\n",
       "       '2017-01-11T00:00:00.000000000', '2017-01-12T00:00:00.000000000',\n",
       "       '2017-01-13T00:00:00.000000000', '2017-01-14T00:00:00.000000000',\n",
       "       '2017-01-15T00:00:00.000000000', '2017-01-16T00:00:00.000000000',\n",
       "       '2017-01-17T00:00:00.000000000', '2017-01-18T00:00:00.000000000',\n",
       "       '2017-01-19T00:00:00.000000000', '2017-01-20T00:00:00.000000000',\n",
       "       '2017-01-21T00:00:00.000000000', '2017-01-22T00:00:00.000000000',\n",
       "       '2017-01-23T00:00:00.000000000', '2017-01-24T00:00:00.000000000',\n",
       "       '2017-01-25T00:00:00.000000000', '2017-01-26T00:00:00.000000000',\n",
       "       '2017-01-27T00:00:00.000000000', '2017-01-28T00:00:00.000000000',\n",
       "       '2017-01-29T00:00:00.000000000', '2017-01-30T00:00:00.000000000',\n",
       "       '2017-01-31T00:00:00.000000000'], dtype='datetime64[ns]')"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "flights.fl_date.unique()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ORD, LAS, DCA, TPA, PHL, ..., YAK, ELM, MOT, LSE, TKI]\n",
       "Length: 298\n",
       "Categories (298, object): [ORD, LAS, DCA, TPA, ..., ELM, MOT, LSE, TKI]"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "flights.origin.unique()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['2014-01-01T00:00:00.000000000', '2014-01-02T00:00:00.000000000',\n",
       "       '2014-01-03T00:00:00.000000000', '2014-01-04T00:00:00.000000000',\n",
       "       '2014-01-05T00:00:00.000000000', '2014-01-06T00:00:00.000000000',\n",
       "       '2014-01-07T00:00:00.000000000', '2014-01-08T00:00:00.000000000',\n",
       "       '2014-01-09T00:00:00.000000000', '2014-01-10T00:00:00.000000000',\n",
       "       '2014-01-11T00:00:00.000000000', '2014-01-12T00:00:00.000000000',\n",
       "       '2014-01-13T00:00:00.000000000', '2014-01-14T00:00:00.000000000',\n",
       "       '2014-01-15T00:00:00.000000000', '2014-01-16T00:00:00.000000000',\n",
       "       '2014-01-17T00:00:00.000000000', '2014-01-18T00:00:00.000000000',\n",
       "       '2014-01-19T00:00:00.000000000', '2014-01-20T00:00:00.000000000',\n",
       "       '2014-01-21T00:00:00.000000000', '2014-01-22T00:00:00.000000000',\n",
       "       '2014-01-23T00:00:00.000000000', '2014-01-24T00:00:00.000000000',\n",
       "       '2014-01-25T00:00:00.000000000', '2014-01-26T00:00:00.000000000',\n",
       "       '2014-01-27T00:00:00.000000000', '2014-01-28T00:00:00.000000000',\n",
       "       '2014-01-29T00:00:00.000000000', '2014-01-30T00:00:00.000000000'], dtype='datetime64[ns]')"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "daily.reset_index().date.unique()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['01M', '04V', '04W', ..., 'NR02', '0CO', 'AXV'], dtype=object)"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "daily.reset_index().station.unique()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The merge version"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [],
   "source": [
    "daily_ = (\n",
    "    daily\n",
    "    .reset_index()\n",
    "    .rename(columns={'date': 'fl_date', 'station': 'origin'})\n",
    "    .assign(origin=lambda x: pd.Categorical(x.origin,\n",
    "                                            categories=flights.origin.cat.categories))\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['2017-01-01T00:00:00.000000000', '2017-01-02T00:00:00.000000000',\n",
       "       '2017-01-03T00:00:00.000000000', '2017-01-04T00:00:00.000000000',\n",
       "       '2017-01-05T00:00:00.000000000', '2017-01-06T00:00:00.000000000',\n",
       "       '2017-01-07T00:00:00.000000000', '2017-01-08T00:00:00.000000000',\n",
       "       '2017-01-09T00:00:00.000000000', '2017-01-10T00:00:00.000000000',\n",
       "       '2017-01-11T00:00:00.000000000', '2017-01-12T00:00:00.000000000',\n",
       "       '2017-01-13T00:00:00.000000000', '2017-01-14T00:00:00.000000000',\n",
       "       '2017-01-15T00:00:00.000000000', '2017-01-16T00:00:00.000000000',\n",
       "       '2017-01-17T00:00:00.000000000', '2017-01-18T00:00:00.000000000',\n",
       "       '2017-01-19T00:00:00.000000000', '2017-01-20T00:00:00.000000000',\n",
       "       '2017-01-21T00:00:00.000000000', '2017-01-22T00:00:00.000000000',\n",
       "       '2017-01-23T00:00:00.000000000', '2017-01-24T00:00:00.000000000',\n",
       "       '2017-01-25T00:00:00.000000000', '2017-01-26T00:00:00.000000000',\n",
       "       '2017-01-27T00:00:00.000000000', '2017-01-28T00:00:00.000000000',\n",
       "       '2017-01-29T00:00:00.000000000', '2017-01-30T00:00:00.000000000',\n",
       "       '2017-01-31T00:00:00.000000000'], dtype='datetime64[ns]')"
      ]
     },
     "execution_count": 99,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "flights.fl_date.unique()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['2014-01-01T00:00:00.000000000', '2014-01-02T00:00:00.000000000',\n",
       "       '2014-01-03T00:00:00.000000000', '2014-01-04T00:00:00.000000000',\n",
       "       '2014-01-05T00:00:00.000000000', '2014-01-06T00:00:00.000000000',\n",
       "       '2014-01-07T00:00:00.000000000', '2014-01-08T00:00:00.000000000',\n",
       "       '2014-01-09T00:00:00.000000000', '2014-01-10T00:00:00.000000000',\n",
       "       '2014-01-11T00:00:00.000000000', '2014-01-12T00:00:00.000000000',\n",
       "       '2014-01-13T00:00:00.000000000', '2014-01-14T00:00:00.000000000',\n",
       "       '2014-01-15T00:00:00.000000000', '2014-01-16T00:00:00.000000000',\n",
       "       '2014-01-17T00:00:00.000000000', '2014-01-18T00:00:00.000000000',\n",
       "       '2014-01-19T00:00:00.000000000', '2014-01-20T00:00:00.000000000',\n",
       "       '2014-01-21T00:00:00.000000000', '2014-01-22T00:00:00.000000000',\n",
       "       '2014-01-23T00:00:00.000000000', '2014-01-24T00:00:00.000000000',\n",
       "       '2014-01-25T00:00:00.000000000', '2014-01-26T00:00:00.000000000',\n",
       "       '2014-01-27T00:00:00.000000000', '2014-01-28T00:00:00.000000000',\n",
       "       '2014-01-29T00:00:00.000000000', '2014-01-30T00:00:00.000000000'], dtype='datetime64[ns]')"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "daily.reset_index().date.unique()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>airline_id</th>\n",
       "      <th>origin_airport_id</th>\n",
       "      <th>origin_airport_seq_id</th>\n",
       "      <th>origin_city_market_id</th>\n",
       "      <th>origin_city_name</th>\n",
       "      <th>dest_airport_id</th>\n",
       "      <th>dest_airport_seq_id</th>\n",
       "      <th>dest_city_market_id</th>\n",
       "      <th>dest_city_name</th>\n",
       "      <th>crs_dep_time</th>\n",
       "      <th>...</th>\n",
       "      <th>tmpf</th>\n",
       "      <th>relh</th>\n",
       "      <th>sped</th>\n",
       "      <th>mslp</th>\n",
       "      <th>p01i</th>\n",
       "      <th>vsby</th>\n",
       "      <th>gust_mph</th>\n",
       "      <th>skyc1</th>\n",
       "      <th>skyc2</th>\n",
       "      <th>skyc3</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>unique_carrier</th>\n",
       "      <th>origin</th>\n",
       "      <th>dest</th>\n",
       "      <th>tail_num</th>\n",
       "      <th>fl_num</th>\n",
       "      <th>fl_date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"5\" valign=\"top\">OO</th>\n",
       "      <th rowspan=\"5\" valign=\"top\">YUM</th>\n",
       "      <th rowspan=\"5\" valign=\"top\">PHX</th>\n",
       "      <th rowspan=\"5\" valign=\"top\">N423SW</th>\n",
       "      <th rowspan=\"5\" valign=\"top\">3068</th>\n",
       "      <th>2017-01-31</th>\n",
       "      <td>20304</td>\n",
       "      <td>16218</td>\n",
       "      <td>1621801</td>\n",
       "      <td>33785</td>\n",
       "      <td>Yuma</td>\n",
       "      <td>14107</td>\n",
       "      <td>1410702</td>\n",
       "      <td>30466</td>\n",
       "      <td>Phoenix</td>\n",
       "      <td>2017-01-31 11:30:00</td>\n",
       "      <td>...</td>\n",
       "      <td>35.747500</td>\n",
       "      <td>81.117917</td>\n",
       "      <td>2.294444</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "      <td>9.229167</td>\n",
       "      <td>NaN</td>\n",
       "      <td>CLR</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-01-31</th>\n",
       "      <td>20304</td>\n",
       "      <td>16218</td>\n",
       "      <td>1621801</td>\n",
       "      <td>33785</td>\n",
       "      <td>Yuma</td>\n",
       "      <td>14107</td>\n",
       "      <td>1410702</td>\n",
       "      <td>30466</td>\n",
       "      <td>Phoenix</td>\n",
       "      <td>2017-01-31 11:30:00</td>\n",
       "      <td>...</td>\n",
       "      <td>18.350000</td>\n",
       "      <td>72.697778</td>\n",
       "      <td>11.250000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "      <td>9.861111</td>\n",
       "      <td>31.603571</td>\n",
       "      <td>CLR</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-01-31</th>\n",
       "      <td>20304</td>\n",
       "      <td>16218</td>\n",
       "      <td>1621801</td>\n",
       "      <td>33785</td>\n",
       "      <td>Yuma</td>\n",
       "      <td>14107</td>\n",
       "      <td>1410702</td>\n",
       "      <td>30466</td>\n",
       "      <td>Phoenix</td>\n",
       "      <td>2017-01-31 11:30:00</td>\n",
       "      <td>...</td>\n",
       "      <td>-9.075000</td>\n",
       "      <td>69.908056</td>\n",
       "      <td>3.647222</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>OVC</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-01-31</th>\n",
       "      <td>20304</td>\n",
       "      <td>16218</td>\n",
       "      <td>1621801</td>\n",
       "      <td>33785</td>\n",
       "      <td>Yuma</td>\n",
       "      <td>14107</td>\n",
       "      <td>1410702</td>\n",
       "      <td>30466</td>\n",
       "      <td>Phoenix</td>\n",
       "      <td>2017-01-31 11:30:00</td>\n",
       "      <td>...</td>\n",
       "      <td>26.321127</td>\n",
       "      <td>71.519859</td>\n",
       "      <td>3.829577</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "      <td>9.929577</td>\n",
       "      <td>NaN</td>\n",
       "      <td>CLR</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-01-31</th>\n",
       "      <td>20304</td>\n",
       "      <td>16218</td>\n",
       "      <td>1621801</td>\n",
       "      <td>33785</td>\n",
       "      <td>Yuma</td>\n",
       "      <td>14107</td>\n",
       "      <td>1410702</td>\n",
       "      <td>30466</td>\n",
       "      <td>Phoenix</td>\n",
       "      <td>2017-01-31 11:30:00</td>\n",
       "      <td>...</td>\n",
       "      <td>-11.388060</td>\n",
       "      <td>73.784179</td>\n",
       "      <td>5.359722</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "      <td>9.576389</td>\n",
       "      <td>NaN</td>\n",
       "      <td>CLR</td>\n",
       "      <td>M</td>\n",
       "      <td>M</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 37 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                       airline_id  \\\n",
       "unique_carrier origin dest tail_num fl_num fl_date                  \n",
       "OO             YUM    PHX  N423SW   3068   2017-01-31       20304   \n",
       "                                           2017-01-31       20304   \n",
       "                                           2017-01-31       20304   \n",
       "                                           2017-01-31       20304   \n",
       "                                           2017-01-31       20304   \n",
       "\n",
       "                                                       origin_airport_id  \\\n",
       "unique_carrier origin dest tail_num fl_num fl_date                         \n",
       "OO             YUM    PHX  N423SW   3068   2017-01-31              16218   \n",
       "                                           2017-01-31              16218   \n",
       "                                           2017-01-31              16218   \n",
       "                                           2017-01-31              16218   \n",
       "                                           2017-01-31              16218   \n",
       "\n",
       "                                                       origin_airport_seq_id  \\\n",
       "unique_carrier origin dest tail_num fl_num fl_date                             \n",
       "OO             YUM    PHX  N423SW   3068   2017-01-31                1621801   \n",
       "                                           2017-01-31                1621801   \n",
       "                                           2017-01-31                1621801   \n",
       "                                           2017-01-31                1621801   \n",
       "                                           2017-01-31                1621801   \n",
       "\n",
       "                                                       origin_city_market_id  \\\n",
       "unique_carrier origin dest tail_num fl_num fl_date                             \n",
       "OO             YUM    PHX  N423SW   3068   2017-01-31                  33785   \n",
       "                                           2017-01-31                  33785   \n",
       "                                           2017-01-31                  33785   \n",
       "                                           2017-01-31                  33785   \n",
       "                                           2017-01-31                  33785   \n",
       "\n",
       "                                                      origin_city_name  \\\n",
       "unique_carrier origin dest tail_num fl_num fl_date                       \n",
       "OO             YUM    PHX  N423SW   3068   2017-01-31             Yuma   \n",
       "                                           2017-01-31             Yuma   \n",
       "                                           2017-01-31             Yuma   \n",
       "                                           2017-01-31             Yuma   \n",
       "                                           2017-01-31             Yuma   \n",
       "\n",
       "                                                       dest_airport_id  \\\n",
       "unique_carrier origin dest tail_num fl_num fl_date                       \n",
       "OO             YUM    PHX  N423SW   3068   2017-01-31            14107   \n",
       "                                           2017-01-31            14107   \n",
       "                                           2017-01-31            14107   \n",
       "                                           2017-01-31            14107   \n",
       "                                           2017-01-31            14107   \n",
       "\n",
       "                                                       dest_airport_seq_id  \\\n",
       "unique_carrier origin dest tail_num fl_num fl_date                           \n",
       "OO             YUM    PHX  N423SW   3068   2017-01-31              1410702   \n",
       "                                           2017-01-31              1410702   \n",
       "                                           2017-01-31              1410702   \n",
       "                                           2017-01-31              1410702   \n",
       "                                           2017-01-31              1410702   \n",
       "\n",
       "                                                       dest_city_market_id  \\\n",
       "unique_carrier origin dest tail_num fl_num fl_date                           \n",
       "OO             YUM    PHX  N423SW   3068   2017-01-31                30466   \n",
       "                                           2017-01-31                30466   \n",
       "                                           2017-01-31                30466   \n",
       "                                           2017-01-31                30466   \n",
       "                                           2017-01-31                30466   \n",
       "\n",
       "                                                      dest_city_name  \\\n",
       "unique_carrier origin dest tail_num fl_num fl_date                     \n",
       "OO             YUM    PHX  N423SW   3068   2017-01-31        Phoenix   \n",
       "                                           2017-01-31        Phoenix   \n",
       "                                           2017-01-31        Phoenix   \n",
       "                                           2017-01-31        Phoenix   \n",
       "                                           2017-01-31        Phoenix   \n",
       "\n",
       "                                                             crs_dep_time  \\\n",
       "unique_carrier origin dest tail_num fl_num fl_date                          \n",
       "OO             YUM    PHX  N423SW   3068   2017-01-31 2017-01-31 11:30:00   \n",
       "                                           2017-01-31 2017-01-31 11:30:00   \n",
       "                                           2017-01-31 2017-01-31 11:30:00   \n",
       "                                           2017-01-31 2017-01-31 11:30:00   \n",
       "                                           2017-01-31 2017-01-31 11:30:00   \n",
       "\n",
       "                                                       ...         tmpf  \\\n",
       "unique_carrier origin dest tail_num fl_num fl_date     ...                \n",
       "OO             YUM    PHX  N423SW   3068   2017-01-31  ...    35.747500   \n",
       "                                           2017-01-31  ...    18.350000   \n",
       "                                           2017-01-31  ...    -9.075000   \n",
       "                                           2017-01-31  ...    26.321127   \n",
       "                                           2017-01-31  ...   -11.388060   \n",
       "\n",
       "                                                            relh       sped  \\\n",
       "unique_carrier origin dest tail_num fl_num fl_date                            \n",
       "OO             YUM    PHX  N423SW   3068   2017-01-31  81.117917   2.294444   \n",
       "                                           2017-01-31  72.697778  11.250000   \n",
       "                                           2017-01-31  69.908056   3.647222   \n",
       "                                           2017-01-31  71.519859   3.829577   \n",
       "                                           2017-01-31  73.784179   5.359722   \n",
       "\n",
       "                                                       mslp  p01i       vsby  \\\n",
       "unique_carrier origin dest tail_num fl_num fl_date                             \n",
       "OO             YUM    PHX  N423SW   3068   2017-01-31   NaN   0.0   9.229167   \n",
       "                                           2017-01-31   NaN   0.0   9.861111   \n",
       "                                           2017-01-31   NaN   0.0  10.000000   \n",
       "                                           2017-01-31   NaN   0.0   9.929577   \n",
       "                                           2017-01-31   NaN   0.0   9.576389   \n",
       "\n",
       "                                                        gust_mph skyc1  skyc2  \\\n",
       "unique_carrier origin dest tail_num fl_num fl_date                              \n",
       "OO             YUM    PHX  N423SW   3068   2017-01-31        NaN   CLR      M   \n",
       "                                           2017-01-31  31.603571   CLR      M   \n",
       "                                           2017-01-31        NaN   OVC      M   \n",
       "                                           2017-01-31        NaN   CLR      M   \n",
       "                                           2017-01-31        NaN   CLR      M   \n",
       "\n",
       "                                                       skyc3  \n",
       "unique_carrier origin dest tail_num fl_num fl_date            \n",
       "OO             YUM    PHX  N423SW   3068   2017-01-31      M  \n",
       "                                           2017-01-31      M  \n",
       "                                           2017-01-31      M  \n",
       "                                           2017-01-31      M  \n",
       "                                           2017-01-31      M  \n",
       "\n",
       "[5 rows x 37 columns]"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m = pd.merge(flights, daily_,\n",
    "             on=['fl_date', 'origin']).set_index(idx_cols).sort_index()\n",
    "\n",
    "m.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Since data-wrangling on its own is never the goal, let's do some quick analysis.\n",
    "Seaborn makes it easy to explore bivariate relationships."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Looking at the various [sky coverage states](https://en.wikipedia.org/wiki/METAR#Cloud_reporting):\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>mean</th>\n",
       "      <th>count</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>skyc1</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>BKN</th>\n",
       "      <td>-8.0</td>\n",
       "      <td>276</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>CLR</th>\n",
       "      <td>-8.0</td>\n",
       "      <td>3033</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>FEW</th>\n",
       "      <td>-8.0</td>\n",
       "      <td>258</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>M</th>\n",
       "      <td>-8.0</td>\n",
       "      <td>180</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>OVC</th>\n",
       "      <td>-8.0</td>\n",
       "      <td>1545</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>SCT</th>\n",
       "      <td>-8.0</td>\n",
       "      <td>246</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>VV</th>\n",
       "      <td>-8.0</td>\n",
       "      <td>57</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       mean  count\n",
       "skyc1             \n",
       "BKN    -8.0    276\n",
       "CLR    -8.0   3033\n",
       "FEW    -8.0    258\n",
       "M      -8.0    180\n",
       "OVC    -8.0   1545\n",
       "SCT    -8.0    246\n",
       "VV     -8.0     57"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m.groupby('skyc1').dep_delay.agg(['mean', 'count']).sort_values(by='mean')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/taugspurger/miniconda3/envs/modern-pandas/lib/python3.6/site-packages/statsmodels/compat/pandas.py:56: FutureWarning: The pandas.core.datetools module is deprecated and will be removed in a future version. Please use the pandas.tseries module instead.\n",
      "  from pandas.core import datetools\n"
     ]
    }
   ],
   "source": [
    "import statsmodels.api as sm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Statsmodels (via [patsy](http://patsy.readthedocs.org/) can automatically convert dummy data to dummy variables in a formula with the `C` function)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table class=\"simpletable\">\n",
       "<caption>OLS Regression Results</caption>\n",
       "<tr>\n",
       "  <th>Dep. Variable:</th>        <td>dep_delay</td>    <th>  R-squared:         </th> <td>   0.000</td> \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Model:</th>                   <td>OLS</td>       <th>  Adj. R-squared:    </th> <td>  -0.004</td> \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Method:</th>             <td>Least Squares</td>  <th>  F-statistic:       </th> <td>4.527e-14</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Date:</th>             <td>Fri, 01 Sep 2017</td> <th>  Prob (F-statistic):</th>  <td>  1.00</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Time:</th>                 <td>17:21:21</td>     <th>  Log-Likelihood:    </th> <td> -4390.8</td> \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>No. Observations:</th>      <td>  2487</td>      <th>  AIC:               </th> <td>   8804.</td> \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Df Residuals:</th>          <td>  2476</td>      <th>  BIC:               </th> <td>   8868.</td> \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Df Model:</th>              <td>    10</td>      <th>                     </th>     <td> </td>    \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Covariance Type:</th>      <td>nonrobust</td>    <th>                     </th>     <td> </td>    \n",
       "</tr>\n",
       "</table>\n",
       "<table class=\"simpletable\">\n",
       "<tr>\n",
       "         <td></td>            <th>coef</th>     <th>std err</th>      <th>t</th>      <th>P>|t|</th>  <th>[0.025</th>    <th>0.975]</th>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Intercept</th>       <td>   -8.0000</td> <td>    3.438</td> <td>   -2.327</td> <td> 0.020</td> <td>  -14.742</td> <td>   -1.258</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>C(skyc1)[T.CLR]</th> <td> 2.782e-15</td> <td>    0.122</td> <td> 2.28e-14</td> <td> 1.000</td> <td>   -0.240</td> <td>    0.240</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>C(skyc1)[T.FEW]</th> <td> 1.943e-16</td> <td>    0.166</td> <td> 1.17e-15</td> <td> 1.000</td> <td>   -0.326</td> <td>    0.326</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>C(skyc1)[T.M]</th>   <td> 3.166e-15</td> <td>    0.194</td> <td> 1.63e-14</td> <td> 1.000</td> <td>   -0.381</td> <td>    0.381</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>C(skyc1)[T.OVC]</th> <td> 3.383e-16</td> <td>    0.124</td> <td> 2.73e-15</td> <td> 1.000</td> <td>   -0.243</td> <td>    0.243</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>C(skyc1)[T.SCT]</th> <td>-2.024e-14</td> <td>    0.284</td> <td>-7.12e-14</td> <td> 1.000</td> <td>   -0.557</td> <td>    0.557</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>C(skyc1)[T.VV ]</th> <td> 3.973e-15</td> <td>    0.224</td> <td> 1.77e-14</td> <td> 1.000</td> <td>   -0.440</td> <td>    0.440</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>tmpf</th>            <td>-3.123e-17</td> <td>    0.002</td> <td>-1.77e-14</td> <td> 1.000</td> <td>   -0.003</td> <td>    0.003</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>relh</th>            <td>-3.144e-17</td> <td>    0.002</td> <td>-1.41e-14</td> <td> 1.000</td> <td>   -0.004</td> <td>    0.004</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>sped</th>            <td>-9.498e-17</td> <td>    0.007</td> <td>-1.38e-14</td> <td> 1.000</td> <td>   -0.013</td> <td>    0.013</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>mslp</th>            <td>-2.251e-16</td> <td>    0.003</td> <td>-6.76e-14</td> <td> 1.000</td> <td>   -0.007</td> <td>    0.007</td>\n",
       "</tr>\n",
       "</table>\n",
       "<table class=\"simpletable\">\n",
       "<tr>\n",
       "  <th>Omnibus:</th>       <td>170.859</td> <th>  Durbin-Watson:     </th> <td>   0.002</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Prob(Omnibus):</th> <td> 0.000</td>  <th>  Jarque-Bera (JB):  </th> <td> 440.406</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Skew:</th>          <td>-0.707</td>  <th>  Prob(JB):          </th> <td>2.33e-96</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Kurtosis:</th>      <td> 1.500</td>  <th>  Cond. No.          </th> <td>1.24e+05</td>\n",
       "</tr>\n",
       "</table>"
      ],
      "text/plain": [
       "<class 'statsmodels.iolib.summary.Summary'>\n",
       "\"\"\"\n",
       "                            OLS Regression Results                            \n",
       "==============================================================================\n",
       "Dep. Variable:              dep_delay   R-squared:                       0.000\n",
       "Model:                            OLS   Adj. R-squared:                 -0.004\n",
       "Method:                 Least Squares   F-statistic:                 4.527e-14\n",
       "Date:                Fri, 01 Sep 2017   Prob (F-statistic):               1.00\n",
       "Time:                        17:21:21   Log-Likelihood:                -4390.8\n",
       "No. Observations:                2487   AIC:                             8804.\n",
       "Df Residuals:                    2476   BIC:                             8868.\n",
       "Df Model:                          10                                         \n",
       "Covariance Type:            nonrobust                                         \n",
       "===================================================================================\n",
       "                      coef    std err          t      P>|t|      [0.025      0.975]\n",
       "-----------------------------------------------------------------------------------\n",
       "Intercept          -8.0000      3.438     -2.327      0.020     -14.742      -1.258\n",
       "C(skyc1)[T.CLR]  2.782e-15      0.122   2.28e-14      1.000      -0.240       0.240\n",
       "C(skyc1)[T.FEW]  1.943e-16      0.166   1.17e-15      1.000      -0.326       0.326\n",
       "C(skyc1)[T.M]    3.166e-15      0.194   1.63e-14      1.000      -0.381       0.381\n",
       "C(skyc1)[T.OVC]  3.383e-16      0.124   2.73e-15      1.000      -0.243       0.243\n",
       "C(skyc1)[T.SCT] -2.024e-14      0.284  -7.12e-14      1.000      -0.557       0.557\n",
       "C(skyc1)[T.VV ]  3.973e-15      0.224   1.77e-14      1.000      -0.440       0.440\n",
       "tmpf            -3.123e-17      0.002  -1.77e-14      1.000      -0.003       0.003\n",
       "relh            -3.144e-17      0.002  -1.41e-14      1.000      -0.004       0.004\n",
       "sped            -9.498e-17      0.007  -1.38e-14      1.000      -0.013       0.013\n",
       "mslp            -2.251e-16      0.003  -6.76e-14      1.000      -0.007       0.007\n",
       "==============================================================================\n",
       "Omnibus:                      170.859   Durbin-Watson:                   0.002\n",
       "Prob(Omnibus):                  0.000   Jarque-Bera (JB):              440.406\n",
       "Skew:                          -0.707   Prob(JB):                     2.33e-96\n",
       "Kurtosis:                       1.500   Cond. No.                     1.24e+05\n",
       "==============================================================================\n",
       "\n",
       "Warnings:\n",
       "[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.\n",
       "[2] The condition number is large, 1.24e+05. This might indicate that there are\n",
       "strong multicollinearity or other numerical problems.\n",
       "\"\"\""
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mod = sm.OLS.from_formula('dep_delay ~ C(skyc1) + tmpf + relh + sped + mslp', data=m)\n",
    "res = mod.fit()\n",
    "res.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1248c8e80>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots()\n",
    "ax.scatter(res.fittedvalues, res.resid, color='k', marker='.', alpha=.25)\n",
    "ax.set(xlabel='Predicted', ylabel='Residual')\n",
    "sns.despine()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Those residuals should look like white noise.\n",
    "Looks like our linear model isn't flexible enough to model the delays,\n",
    "but I think that's enough for now.\n",
    "\n",
    "---\n",
    "\n",
    "We'll talk more about indexes in the Tidy Data and Reshaping section.\n",
    "[Let me know](http://twitter.com/tomaugspurger) if you have any feedback.\n",
    "Thanks for reading!"
   ]
  }
 ],
 "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.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
