{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# General Python Tutorial" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The tutorial is designed to touch upon \n", "> 1. Finding data from ArcGIS Hub\n", "\n", "> 2. Loading and Visualizing it using ArcGIS API for Python (API)\n", "\n", "> 3. Extract it as a Python dataframe for basic exploratory analysis\n", "\n", "> 4. Query the data for specific results using the API\n", "\n", "> 5. Customize map results using API" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's start from the bare basics..\n", "\n", "1. For those new to Python, [here](http://www.pythonforbeginners.com/basics/python-websites-tutorials) is a list of online resourses available to learn and familiarize yourself with Python.\n", "\n", "2. [Anaconda](https://www.continuum.io/downloads), an open source distribution of R and Python is used to install Python version 3.6. All the packages used in the next code cell (except geopandas) come along with the Anaconda installation of Python.\n", "\n", "3. To install geopandas, execute the following command _after_ Anaconda has been installed.\n", "\n", "__`conda install -c conda-forge geopandas`__" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We start by importing necessary packages" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import pandas as pd\n", "import geopandas as gpd\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "\n", "sns.set(color_codes=True)\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A simple breakdown of these packages..\n", "\n", "> [__Pandas__](https://pypi.python.org/pypi/pandas/) : To load data as a table and enable working with tabular data.\n", "\n", "> [__Geopandas__](https://pypi.python.org/pypi/geopandas/0.2.1) : An extension of Pandas that supports working with geospatial data.\n", "\n", "> [__Numpy__](https://pypi.python.org/pypi/numpy/1.13.1) : Supports array processing for numbers, strings, records and objects\n", "\n", "> [__Matplotlib__](https://pypi.python.org/pypi/matplotlib/2.0.2) : Package for plotting and Python visualization\n", "\n", "> [__Seaborn__](https://pypi.python.org/pypi/seaborn/0.8) : Package for making attractive and informative statistical graphics in Python\n", "\n", "\n", "The last two lines of code in the cell above, adopt the color styles of seaborn and allow for displaying plots within this notebook, as opposed to displaying them in another browser window." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 1: Finding data from ArcGIS hub" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Look for the dataset in the search bar as shown on the [ArcGIS Hub Open Data](http://hub.arcgis.com/pages/open-data) page.\n", "\n", "The dataset used through this tutorial is the [DC Bicyclelanes](opendata.dc.gov/datasets/bicycle-lanes) dataset.\n", "\n", "The Bicycle Lanes dataset for DC contains information such as length of the bike lane, year installed, additional notes, segment id for the street it falls on, etc for each bike lane. Additional information about each field in the dataset can be found [here](http://www.arcgis.com/sharing/rest/content/items/294e062cdf2c48d5b9cbc374d9709bc0/info/metadata/metadata.xml?format=default&output=html)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![home](https://user-images.githubusercontent.com/13968196/36805045-55274cd8-1c8a-11e8-8c89-9aed63f03543.PNG)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "When you click on the dataset in the search results, it takes you to the details of the dastaset. Click on the __'API Explorer'__ tab as shown below." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![overview](https://user-images.githubusercontent.com/13968196/36805050-5799aca4-1c8a-11e8-96d4-5a36819c24b4.PNG)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once under the 'API Explorer' tab, copy only the selected portion of the 'Query URL'. This ensures that that the data is __not returned in the JSON format__." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![serviceurl](https://user-images.githubusercontent.com/13968196/36805068-6409e9e0-1c8a-11e8-93b0-d8f35f13e75d.PNG)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 2.1: Loading the data using ArcGIS API for Python" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The copied URL is stored in the variable __lyr_url__ and using the __arcgis__ package of Python it is loaded as a feature/map layer in Python\n", "\n", "The __arcgis__ Python package allows automating tasks that integrate big data analysis with one's web GIS. \n", "\n", "It can be installed using [conda](https://developers.arcgis.com/python/guide/install-and-set-up/#Install-using-Conda) as well." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from arcgis.features import FeatureLayer\n", "lyr_url = 'https://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Transportation_WebMercator/MapServer/2'\n", "\n", "bike_layer = FeatureLayer(lyr_url)\n", "bike_layer" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To learn more about the package and its usage follow this [link](https://developers.arcgis.com/python/guide/overview-of-the-arcgis-api-for-python/).\n", "\n", "Experienced Python users could also read the [API docs](http://esri.github.io/arcgis-python-api/apidoc/html/).\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using the following lines of code, we output the fields/attributes of the dataset" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "OBJECTID\n", "FACILITYID\n", "STREETSEGID\n", "SOURCEID\n", "BIKELANELENGTH\n", "FACILITY\n", "PROPOSEDCYCLETRACK\n", "Shape\n", "Shape_Length\n", "TRAVELDIRECTION\n", "NOTES\n", "BIKELANE_YEAR\n", "PLANSREADY\n", "GAP\n", "GAP_NOTES\n", "NEED_SYMBOL\n", "NEED_SYM_1\n", "REPAINT_LINE\n", "YEAR_INSTALLED\n" ] } ], "source": [ "for f in bike_layer.properties.fields:\n", " print(f['name'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We now retreive the entire dataset in __all_features__ and get a count of all the rows in the dataset" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Total number of rows in the dataset: \n", "1370\n" ] } ], "source": [ "all_features = bike_layer.query()\n", "print('Total number of rows in the dataset: ')\n", "print(len(all_features.features))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 2.2: Visualizing it using the API" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from arcgis.gis import GIS\n", "gis = GIS()\n", "\n", "#Here we select a zoom level of 13, purely based on judgement of location and data to be displayed\n", "map1 = gis.map('Washington, DC', 13)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the following step we add the Bikelanes as a layer superimposing the basemap of Washington, DC initialized above.\n", "\n", "The \"url\" attribute is provided with the __Service URL__" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "ed0dbd0f60d04fa48069064d0576b78b" } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "map1.add_layer({\"type\":\"FeatureLayer\",\n", " \"url\":\"https://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Transportation_WebMercator/MapServer/2\",\n", " })\n", "map1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![map1](https://user-images.githubusercontent.com/13968196/36805092-75a71330-1c8a-11e8-8180-e3c5bac1d860.PNG)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 3.1: Loading the data as a Pandas DataFrame" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The variable __all_features__ is of datatype arcgis FeatureSet.\n", "\n", "In order to use this data as a tabular dataset, we need to store it as a Pandas DataFrame, as shown below." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BIKELANELENGTHBIKELANE_YEARFACILITYFACILITYIDGAPGAP_NOTESNEED_SYMBOLNEED_SYM_1NOTESOBJECTIDPLANSREADYPROPOSEDCYCLETRACKREPAINT_LINESOURCEIDSTREETSEGIDShape_LengthTRAVELDIRECTIONYEAR_INSTALLEDSHAPE
00.0094550Existing Bike LaneSEGID- 9854NoneNone1None15135550985415.2168462008{'paths': [[[-8573273.977615476, 4715455.45970...
10.0767540Existing Bike LaneSEGID- 10198NoneNoneCOG 95, 1975 plan, public input2None1513555510198123.5249762008{'paths': [[[-8573264.662602307, 4715472.71048...
20.0586100Existing Bike LaneSEGID- 9167NoneNoneCOG 95, 1975 plan, public input3None15135560916794.3228952008{'paths': [[[-8573183.827335583, 4715609.70743...
30.0268910Existing Bike LaneSEGID- 12337NoneNoneCOG 95, 1975 plan, public input4None151355651233743.2764712008{'paths': [[[-8573122.896706875, 4715714.84043...
40.1723850Existing Bike LaneSEGID- 10611NoneNoneCOG 95, 1975 plan, public input5None1513558010611277.4257022008{'paths': [[[-8572973.134739578, 4715973.04009...
\n", "
" ], "text/plain": [ " BIKELANELENGTH BIKELANE_YEAR FACILITY FACILITYID GAP \\\n", "0 0.009455 0 Existing Bike Lane SEGID- 9854 \n", "1 0.076754 0 Existing Bike Lane SEGID- 10198 \n", "2 0.058610 0 Existing Bike Lane SEGID- 9167 \n", "3 0.026891 0 Existing Bike Lane SEGID- 12337 \n", "4 0.172385 0 Existing Bike Lane SEGID- 10611 \n", "\n", " GAP_NOTES NEED_SYMBOL NEED_SYM_1 NOTES OBJECTID \\\n", "0 None None 1 \n", "1 None None COG 95, 1975 plan, public input 2 \n", "2 None None COG 95, 1975 plan, public input 3 \n", "3 None None COG 95, 1975 plan, public input 4 \n", "4 None None COG 95, 1975 plan, public input 5 \n", "\n", " PLANSREADY PROPOSEDCYCLETRACK REPAINT_LINE SOURCEID STREETSEGID \\\n", "0 None 15135550 9854 \n", "1 None 15135555 10198 \n", "2 None 15135560 9167 \n", "3 None 15135565 12337 \n", "4 None 15135580 10611 \n", "\n", " Shape_Length TRAVELDIRECTION YEAR_INSTALLED \\\n", "0 15.216846 2008 \n", "1 123.524976 2008 \n", "2 94.322895 2008 \n", "3 43.276471 2008 \n", "4 277.425702 2008 \n", "\n", " SHAPE \n", "0 {'paths': [[[-8573273.977615476, 4715455.45970... \n", "1 {'paths': [[[-8573264.662602307, 4715472.71048... \n", "2 {'paths': [[[-8573183.827335583, 4715609.70743... \n", "3 {'paths': [[[-8573122.896706875, 4715714.84043... \n", "4 {'paths': [[[-8572973.134739578, 4715973.04009... " ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#store as dataframe\n", "data = all_features.df\n", "\n", "#View first 5 rows\n", "data.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since this is a spatial dataset (contains geometry that can be plotted on a map), we will convert it to a geodataframe to view its details." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 1370 entries, 0 to 1369\n", "Data columns (total 19 columns):\n", "BIKELANELENGTH 1370 non-null float64\n", "BIKELANE_YEAR 1370 non-null int64\n", "FACILITY 1370 non-null object\n", "FACILITYID 1370 non-null object\n", "GAP 1370 non-null object\n", "GAP_NOTES 1370 non-null object\n", "NEED_SYMBOL 0 non-null object\n", "NEED_SYM_1 0 non-null object\n", "NOTES 1370 non-null object\n", "OBJECTID 1370 non-null int64\n", "PLANSREADY 1370 non-null object\n", "PROPOSEDCYCLETRACK 1370 non-null object\n", "REPAINT_LINE 0 non-null object\n", "SOURCEID 1370 non-null object\n", "STREETSEGID 1370 non-null int64\n", "Shape_Length 1370 non-null float64\n", "TRAVELDIRECTION 1370 non-null object\n", "YEAR_INSTALLED 1370 non-null int64\n", "SHAPE 1370 non-null object\n", "dtypes: float64(2), int64(4), object(13)\n", "memory usage: 203.4+ KB\n" ] } ], "source": [ "data_gdf = gpd.GeoDataFrame(data)\n", "data_gdf.info()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### The result above shows that this dataset has 1370 rows and 19 columns, of which 3 columns (NEED_SYMBOL, NEED_SYM_1, REPAINT_LINE) have no data. We can also find the datatype of each column from this result." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 3.2: Basic exploratory analysis" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's start by computing the total distance of bike lanes in DC" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "96.47902169999992" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.sum(data['BIKELANELENGTH'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### We just found out the total coverage of bike lanes in DC, which is approximately 96.48 decimal miles.\n", "\n", "\n", "* Similarly we could also use __`np.mean(array_name)`__ and __`np.median(array_name)`__ to compute those values." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will now find the types of bike lanes stored in the column __'FACILITY'__ and visualize the number of bike lanes based on type." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array(['Existing Bike Lane', 'Shared Lane', 'Climbing Lane', 'Cycle Track',\n", " 'Contraflow Bike Lane', 'Bus/Bike Lane', ' '], dtype=object)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#Gives unique values in a dataframe column\n", "data['FACILITY'].unique()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's now find the number of bike lanes of each unique type (frequency) and store it in the variable __counts__" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": true }, "outputs": [], "source": [ "counts = data['FACILITY'].value_counts()" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Existing Bike Lane 908\n", "Shared Lane 258\n", "Cycle Track 88\n", "Climbing Lane 62\n", "Contraflow Bike Lane 45\n", " 5\n", "Bus/Bike Lane 4\n", "Name: FACILITY, dtype: int64\n" ] } ], "source": [ "print(counts)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will now visualize __counts__ as a bar chart" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\nE/h/WhCGf7k5PLwAAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "#Generates bar graph\n", "ax = counts.plot(kind='bar', figsize=(10, 10), legend=True, fontsize=12)\n", "\n", "#X axis text and display style of categories\n", "ax.set_xlabel(\"Facility\", fontsize=12)\n", "plt.xticks(rotation=45)\n", "\n", "#Y axis text\n", "ax.set_ylabel(\"Count\", fontsize=12)\n", "\n", "#Title\n", "ax.set_title(\"Types of Bike Lane\", fontsize=20)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 4: Query the data for specific results" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We now try to query the dataset based on certain filters using the __where__ clause qithin the query. \n", "\n", "In this example, we check for _bikes installed in the last 5 years_.\n", "\n", "__NOTE:__ These filters can only be applied to NUMERICAL data fields" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of bike lanes installed in the last 5 years (2012-2016): \n" ] }, { "data": { "text/plain": [ "566" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "query_result = bike_layer.query(where=\"YEAR_INSTALLED>2011\")\n", "print('Number of bike lanes installed in the last 5 years (2012-2016): ')\n", "len(query_result.features)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "These results can also be stored as a Pandas DataFrame for analysis." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": true }, "outputs": [], "source": [ "#store as dataframe\n", "data_5yrs = query_result.df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To get the number of bikes installed each year, we perform a __values_counts()__ on this dataframe over the __`YEAR_INSTALLED`__ field" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2012 162\n", "2014 160\n", "2015 86\n", "2013 82\n", "2016 76\n", "Name: YEAR_INSTALLED, dtype: int64" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data_5yrs['YEAR_INSTALLED'].value_counts()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 5: Customize map results" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's start by finding the various unique values in the column __'YEAR_INSTALLED'__" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([2008, 2005, 1980, 2007, 2010, 2013, 2014, 2002, 2011, 2009, 2004,\n", " 2012, 2006, 2003, 2015, 2016, 0, 2001], dtype=int64)" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data['YEAR_INSTALLED'].unique()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For the following map, we have used the same location and zoom level.\n", "\n", "The only change is the __choice of basemap__ used. The other available basemaps are:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['streets',\n", " 'satellite',\n", " 'hybrid',\n", " 'topo',\n", " 'gray',\n", " 'dark-gray',\n", " 'oceans',\n", " 'national-geographic',\n", " 'terrain',\n", " 'osm']" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "map1.basemaps" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": true }, "outputs": [], "source": [ "map2 = gis.map('Washington, DC', 13)\n", "#setting a basemap to the map\n", "map2.basemap = 'gray'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we use the __ClassedColorRenderer__ in order to render different colors on the map, based on the values in the __field_name__. \n", "\n", "__NOTE:__ The column provided as \"field_name\" can only be of NUMERICAL data type." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "70f26430e5a141f7822f624ec467bdd1" } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "map2.add_layer({\"type\":\"FeatureLayer\",\n", " \"url\":\"https://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Transportation_WebMercator/MapServer/2\",\n", " \"renderer\":\"ClassedColorRenderer\", \"field_name\":\"YEAR_INSTALLED\"\n", " })\n", "map2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![map2](https://user-images.githubusercontent.com/13968196/36805088-750a2b38-1c8a-11e8-9f75-9d7c8337562e.PNG)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As per the map above, the darker the bike lanes the newer the construction. The lighter bike lanes signify an older year of installation." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Next Steps:\n", "\n", "> Examples of other features that could be added to this map are: \n", "\n", "> 1. The street layer for DC, to estimate what proportion of streets in DC are bike lanes.\n", "\n", "> 2. Bike trails of DC to follow routes connected by these bike lanes.\n", "\n", "> 3. Demographics data to see if the bike lanes are appropriately connecting the most populous regions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To see other analyses examples of using the ArcGIS API for Python, follow [this](https://github.com/Esri/arcgis-python-api/tree/master/samples/04_gis_analysts_data_scientists) link to the API's Github." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" } }, "nbformat": 4, "nbformat_minor": 2 }