{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Python and MySQL"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# First step is always import the necessary packages\n",
    "import pymysql"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Connections and Cursors\n",
    "With SQL, just as with Mongo, we need to first create a **connection** to our database. Through this connection we can retreive database meta data, but can also instantiate a **curosr**.\n",
    " - Just as with Mongo, the **cursor** is used to interact with the database and will store the results of any executed queries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "scrolled": true,
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "import pymysql.cursors\n",
    "\n",
    "# Connect to the database\n",
    "connection = pymysql.connect(host='gwumysql-restore.cazdwdlcg6dm.us-east-2.rds.amazonaws.com',\n",
    "                             user='EMSE6992',\n",
    "                             port=3306,\n",
    "                             db='EMSE6992',\n",
    "                             password='MySQLpass')\n",
    "\n",
    "#From our connection we need a cursor, which acts as our interface into the database\n",
    "cur = connection.cursor()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "SQL **cursor** objects have a basic functional loop:\n",
    " 1. **cursor**.execute(_query_)\n",
    "  - The **cursor** must first execute a _query_ whoes response may be stored within the **cursor**\n",
    " 2. **cursor**._fetch_() or *iterate through the cursor*\n",
    "  - Once executed, the results of a _query_ can be retreived from the **cursor**, if any results exist\n",
    "  \n",
    "*NOTE: This is a different functional loop from __Mongo's__ cursor loop*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The number of rows returned: 5\n"
     ]
    }
   ],
   "source": [
    "#From a cursor we can execute SQL directly\n",
    "res = cur.execute(\"Select * From users LIMIT 5\")\n",
    "print(f\"The number of rows returned: {res}\") #the output from execute() will be the number of records returned"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can *fetch* the results (*__fetchall()__ will return all records*):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(datetime.date(2018, 5, 25), \"creator of knowyourmeme's meme of the day 15th november 2019 - @AetherionArt did the avatar & @macagilart did the header\", 18739, 1188, '1000026776872144897', 21, None, 'fooly', 'mashcore4mums', 20970, None, None)\n"
     ]
    }
   ],
   "source": [
    "users = cur.fetchall()\n",
    "for user in users:\n",
    "    print(user) # We can now take a look at what was returned\n",
    "    break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(datetime.date(2018, 5, 25), \"creator of knowyourmeme's meme of the day 15th november 2019 - @AetherionArt did the avatar & @macagilart did the header\", 18739, 1188, '1000026776872144897', 21, None, 'fooly', 'mashcore4mums', 20970, None, None)\n"
     ]
    }
   ],
   "source": [
    "res = cur.execute(\"Select * From users LIMIT 5\")\n",
    "for user in users:\n",
    "    print(user)\n",
    "    break"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Each **execute()** refreshes the information stored in the **cursor**, meaning we can continously query the database.\n",
    "\n",
    "Here we see that by calling **fetchone()** rather than **fetchall()** we won't get a list, but rather directly access the top _tuple_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(datetime.date(2018, 5, 25),\n",
       " \"creator of knowyourmeme's meme of the day 15th november 2019 - @AetherionArt did the avatar & @macagilart did the header\",\n",
       " 18739,\n",
       " 1188,\n",
       " '1000026776872144897',\n",
       " 21,\n",
       " None,\n",
       " 'fooly',\n",
       " 'mashcore4mums',\n",
       " 20970,\n",
       " None,\n",
       " None)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cur.execute(\"Select * From users\")\n",
    "\n",
    "data = cur.fetchone()\n",
    "data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "86202"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cur.execute(\"Select * From users\")\n",
    "\n",
    "data = cur.fetchall()\n",
    "len(data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Dict Cursor\n",
    "We can define types of cursors when connecting to a database, which alters the format of the returned data\n",
    " - Done by adding a _cursorclass_ param to our connection"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "connection = pymysql.connect(host='gwumysql-restore.cazdwdlcg6dm.us-east-2.rds.amazonaws.com',\n",
    "                             user='EMSE6992',\n",
    "                             port=3306,\n",
    "                             db='EMSE6992',\n",
    "                             password='MySQLpass',\n",
    "                             cursorclass=pymysql.cursors.DictCursor) # This is the significant line!\n",
    "\n",
    "cur = connection.cursor()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'created_date': datetime.date(2018, 5, 25),\n",
       " 'description': \"creator of knowyourmeme's meme of the day 15th november 2019 - @AetherionArt did the avatar & @macagilart did the header\",\n",
       " 'favorites_count': 18739,\n",
       " 'friends_count': 1188,\n",
       " 'user_id': '1000026776872144897',\n",
       " 'listed_count': 21,\n",
       " 'location': None,\n",
       " 'name': 'fooly',\n",
       " 'screen_name': 'mashcore4mums',\n",
       " 'statuses_count': 20970,\n",
       " 'url': None,\n",
       " 'verified': None}"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cur.execute(\"SELECT * FROM users LIMIT 1;\")\n",
    "cur.fetchone()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# In Class Work\n",
    "Create a connection to the **EMSE6992 database** and run a query to determine how many users have tweeted more than 1,000 times, using the **statuses table**:\n",
    "\n",
    "*Expected Result: 8 users*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Space for work\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "How Could we implement this in Mongo?\n",
    "\n",
    "----"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## SQL - Dataframe Compatibility\n",
    "Given that both SQL and Dataframes both work with tabular data, it makes these two technologies easily integratable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "\n",
    "res = cur.execute(\"Select * From users LIMIT 100\")\n",
    "users = cur.fetchall()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Since the cursor returns a list of dictionaries, we are setup to dump the data into a pandas DataFrame"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>created_date</th>\n",
       "      <th>description</th>\n",
       "      <th>favorites_count</th>\n",
       "      <th>friends_count</th>\n",
       "      <th>user_id</th>\n",
       "      <th>listed_count</th>\n",
       "      <th>location</th>\n",
       "      <th>name</th>\n",
       "      <th>screen_name</th>\n",
       "      <th>statuses_count</th>\n",
       "      <th>url</th>\n",
       "      <th>verified</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2018-05-25</td>\n",
       "      <td>creator of knowyourmeme's meme of the day 15th...</td>\n",
       "      <td>18739.0</td>\n",
       "      <td>1188.0</td>\n",
       "      <td>1000026776872144897</td>\n",
       "      <td>21.0</td>\n",
       "      <td>None</td>\n",
       "      <td>fooly</td>\n",
       "      <td>mashcore4mums</td>\n",
       "      <td>20970</td>\n",
       "      <td>None</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2018-05-25</td>\n",
       "      <td>-_-</td>\n",
       "      <td>5281.0</td>\n",
       "      <td>120.0</td>\n",
       "      <td>1000073751457824768</td>\n",
       "      <td>NaN</td>\n",
       "      <td>uncomfortable</td>\n",
       "      <td>Cas</td>\n",
       "      <td>Amai_Neo</td>\n",
       "      <td>1260</td>\n",
       "      <td>None</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2018-05-25</td>\n",
       "      <td>Lifelong learner. \\n\\nD2C brands + iOS &amp; Shopi...</td>\n",
       "      <td>4240.0</td>\n",
       "      <td>385.0</td>\n",
       "      <td>1000084374468128768</td>\n",
       "      <td>10.0</td>\n",
       "      <td>Earth</td>\n",
       "      <td>Max Grev</td>\n",
       "      <td>max_grev</td>\n",
       "      <td>855</td>\n",
       "      <td>https://t.co/J7KuZFVRRI</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2009-12-28</td>\n",
       "      <td>Be an encourager. The World has plenty of crit...</td>\n",
       "      <td>4566.0</td>\n",
       "      <td>477.0</td>\n",
       "      <td>100009243</td>\n",
       "      <td>1.0</td>\n",
       "      <td>Leicester, England</td>\n",
       "      <td>Aakash Jabbar</td>\n",
       "      <td>mangianees</td>\n",
       "      <td>3816</td>\n",
       "      <td>https://t.co/Afy69InVdg</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2009-12-28</td>\n",
       "      <td>Culture Writer | I Get It In Ohio - Just using...</td>\n",
       "      <td>106836.0</td>\n",
       "      <td>2069.0</td>\n",
       "      <td>100009746</td>\n",
       "      <td>26.0</td>\n",
       "      <td>Columbus, OH</td>\n",
       "      <td>Stimmy Lovato</td>\n",
       "      <td>MikeishaDache</td>\n",
       "      <td>178768</td>\n",
       "      <td>https://t.co/IILZF0YLqw</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  created_date                                        description  \\\n",
       "0   2018-05-25  creator of knowyourmeme's meme of the day 15th...   \n",
       "1   2018-05-25                                                -_-   \n",
       "2   2018-05-25  Lifelong learner. \\n\\nD2C brands + iOS & Shopi...   \n",
       "3   2009-12-28  Be an encourager. The World has plenty of crit...   \n",
       "4   2009-12-28  Culture Writer | I Get It In Ohio - Just using...   \n",
       "\n",
       "   favorites_count  friends_count              user_id  listed_count  \\\n",
       "0          18739.0         1188.0  1000026776872144897          21.0   \n",
       "1           5281.0          120.0  1000073751457824768           NaN   \n",
       "2           4240.0          385.0  1000084374468128768          10.0   \n",
       "3           4566.0          477.0            100009243           1.0   \n",
       "4         106836.0         2069.0            100009746          26.0   \n",
       "\n",
       "             location           name    screen_name  statuses_count  \\\n",
       "0                None          fooly  mashcore4mums           20970   \n",
       "1       uncomfortable            Cas       Amai_Neo            1260   \n",
       "2               Earth       Max Grev       max_grev             855   \n",
       "3  Leicester, England  Aakash Jabbar     mangianees            3816   \n",
       "4        Columbus, OH  Stimmy Lovato  MikeishaDache          178768   \n",
       "\n",
       "                       url  verified  \n",
       "0                     None       NaN  \n",
       "1                     None       NaN  \n",
       "2  https://t.co/J7KuZFVRRI       NaN  \n",
       "3  https://t.co/Afy69InVdg       NaN  \n",
       "4  https://t.co/IILZF0YLqw       NaN  "
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.DataFrame.from_dict(users)\n",
    "df[:5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This obviously allows us to work with the data with a more robust API"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "              favorites_count  friends_count  listed_count  statuses_count\n",
      "created_date                                                              \n",
      "2007-11-06         947.000000     420.000000  21112.000000   363488.000000\n",
      "2009-12-28       30468.818182     607.545455    243.222222    41672.636364\n",
      "2009-12-29        3275.250000    1223.750000    513.750000    72326.000000\n",
      "2012-12-09       22373.500000     723.000000           NaN     6708.000000\n",
      "2012-12-10       18302.000000     744.666667     20.714286    12219.666667\n",
      "2018-05-25       10281.000000     461.250000     11.666667     6263.250000\n",
      "2018-05-26       33416.266667     946.400000     29.666667    10082.000000\n",
      "2018-05-27       20586.333333     230.555556      7.200000    18210.333333\n",
      "2018-05-28       20539.866667    1392.200000     33.545455     9590.800000\n",
      "2018-05-29       33173.933333     577.200000     28.545455    14812.666667\n",
      "2018-05-30       20223.615385     541.538462     44.777778    12599.230769\n",
      "2018-05-31       36709.000000    1259.000000     45.000000    30776.000000\n"
     ]
    }
   ],
   "source": [
    "df.drop('verified', axis=1, inplace=True)\n",
    "print(df.groupby(['created_date']).mean())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### We can also read data directly into pandas\n",
    "\n",
    "By passing a connection object into pandas' **read_sql(_query_, _conn_)** we can create DataFrame's directly from a query."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>screen_name</th>\n",
       "      <th>user_id</th>\n",
       "      <th>favorites_count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>mashcore4mums</td>\n",
       "      <td>1000026776872144897</td>\n",
       "      <td>18739</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>mashcore4mums</td>\n",
       "      <td>1000026776872144897</td>\n",
       "      <td>18739</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>mashcore4mums</td>\n",
       "      <td>1000026776872144897</td>\n",
       "      <td>18739</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>mashcore4mums</td>\n",
       "      <td>1000026776872144897</td>\n",
       "      <td>18739</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Amai_Neo</td>\n",
       "      <td>1000073751457824768</td>\n",
       "      <td>5281</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>Amai_Neo</td>\n",
       "      <td>1000073751457824768</td>\n",
       "      <td>5281</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>max_grev</td>\n",
       "      <td>1000084374468128768</td>\n",
       "      <td>4240</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>mangianees</td>\n",
       "      <td>100009243</td>\n",
       "      <td>4566</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>MikeishaDache</td>\n",
       "      <td>100009746</td>\n",
       "      <td>106836</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>MikeishaDache</td>\n",
       "      <td>100009746</td>\n",
       "      <td>106836</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     screen_name              user_id  favorites_count\n",
       "0  mashcore4mums  1000026776872144897            18739\n",
       "1  mashcore4mums  1000026776872144897            18739\n",
       "2  mashcore4mums  1000026776872144897            18739\n",
       "3  mashcore4mums  1000026776872144897            18739\n",
       "4       Amai_Neo  1000073751457824768             5281\n",
       "5       Amai_Neo  1000073751457824768             5281\n",
       "6       max_grev  1000084374468128768             4240\n",
       "7     mangianees            100009243             4566\n",
       "8  MikeishaDache            100009746           106836\n",
       "9  MikeishaDache            100009746           106836"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conn = pymysql.connect(host='gwumysql-restore.cazdwdlcg6dm.us-east-2.rds.amazonaws.com',\n",
    "                             user='EMSE6992',\n",
    "                             port=3306,\n",
    "                             db='EMSE6992',\n",
    "                             password='MySQLpass')\n",
    "\n",
    "df = pd.read_sql(\"SELECT users.screen_name, users.user_id, users.favorites_count FROM users JOIN statuses On users.user_id = statuses.user_id limit 10\", conn)\n",
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# In Class Work\n",
    "Using a SQL query, populate a dataframe with the total number of statuses made per location. Using the dataframe, create a histogram and bar plot. Limit your results to the top 25 results.\n",
    "\n",
    "*Note: location is a user field*\n",
    "\n",
    "*Hint: Dataframes have a `Dataframe.plot.bar()` and a `Dataframe.plot.hist()` method built into them.*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<AxesSubplot:xlabel='location'>"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Space for work\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "df_class = pd.read_sql(\"\"\"\n",
    "SELECT location, count(*) as num FROM statuses \n",
    "    INNER JOIN users\n",
    "    On users.user_id = statuses.user_id \n",
    "GROUP BY location \n",
    "ORDER BY num DESC\n",
    "\"\"\", conn)\n",
    "\n",
    "df_class['location'] = df_class['location'].astype('str')\n",
    "df_class[1:25].plot.bar(x='location', y='num')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Table Alterations\n",
    "Whenever executing a query that will alter the information in a database (creating/removing/altering tables/records) we need to commit those changes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "query = \"INSERT INTO statuses (list of cols) VALUES (place for values)\"\n",
    "cur.execute(query)\n",
    "\n",
    "# NOTE: We commit using the connection!\n",
    "conn.commit()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## IN Class Work\n",
    "Insert yourself as a **movie** into the **movies** table\n",
    "\n",
    "*Note: You must include a title and year**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Space for work\n",
    "cur = "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Extra - Input Sanitzation\n",
    "This is more a consideration for developing applications, but an important principal of working with databases is sanitization\n",
    "\n",
    "<img src='https://imgs.xkcd.com/comics/exploits_of_a_mom.png'>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "title = \"Robert'); Drop Table movie_data;\"\n",
    "{cursor_object}.execute(f\"INSERT INTO movie_data (title, year) VALUES ({name}, '2020')\")"
   ]
  }
 ],
 "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.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}