{ "metadata": { "name": "", "signature": "sha256:86728bd1f81b030b0152580821dbc6554431bd42b99cb9368907a6506fff70f1" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Geospatial Data in Python: Database, Desktop, and the Web\n", "## Tutorial (Part 4)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Creating a simple GeoSeries" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from shapely.geometry import Polygon\n", "from geopandas import GeoSeries, GeoDataFrame\n", "\n", "# Create three simple polygons\n", "p1 = Polygon([(0, 0), (1, 0), (1, 1)])\n", "p2 = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])\n", "p3 = Polygon([(2, 0), (3, 0), (3, 1), (2, 1)])\n", "\n", "s = GeoSeries([p1, p2, p3])\n", "s" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Some geographic operations return a normal pandas object. The `area` property of a `GeoSeries` will return a pandas `Series` containing the area of each item in the `GeoSeries`:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print(s.area)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Simple file I/O" ] }, { "cell_type": "code", "collapsed": false, "input": [ "# Specify file name\n", "import os\n", "boro_file = os.path.join(\"..\", \"data\", \"nybb\", \"nybb.shp\")\n", "\n", "# Create from file (one line)\n", "boros = GeoDataFrame.from_file(boro_file)\n", "\n", "# Do some pandas stuff\n", "boros.set_index('BoroCode', inplace=True)\n", "boros.sort()\n", "boros" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Plotting a simple GeoSeries" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "\n", "f, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 5), sharey=True)\n", "s.plot(axes=ax1)\n", "ax1.set_title(\"Original Polygons\")\n", "ax1.set_xlim(-0.5, 3.5)\n", "s.buffer(0.4).plot(axes=ax2)\n", "ax2.set_title(\"Buffered Polygons\")\n", "ax2.set_ylim(-0.5, 1.5)\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Plotting a GeoDataFrame" ] }, { "cell_type": "code", "collapsed": false, "input": [ "fig = plt.figure(figsize=(8, 8))\n", "ax = boros.plot() # Regular plot\n", "# We can access and plot the geometries directly as well\n", "ax = boros.geometry.convex_hull.plot(axes=ax)\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## GeoPandas makes databases easy\n", "\n", "You can access `PostGIS` and other spatially aware databases with a similar `API` to Pandas. The added bonus here is that GeoPandas *understands* geospatial data (such as `WKB`):\n", "\n", "It automatically converts `WKB` to the appropriate Shapely `geometry` type.\n", "\n", "*Note: If you're following along, you can use the included shapefile instead of a database*" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import geopandas as gpd\n", "\n", "wifi_file = os.path.join(\"..\", \"data\", \"wifi\", \"wifi.shp\")\n", "\n", "df_geo = gpd.read_file(wifi_file)\n", "df_geo.head()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Now that we have a GeoDataFrame...\n", "\n", "### We can do all sorts of fun things!\n", "\n", "Like compute **summaries** of the geometries:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "# What is the total area of all 5 NYC boroughs?\n", "print(boros.area.sum())" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "...change the **CRS**:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "# Convert from NY State Plane to WGS84 (long/lat)\n", "df_wgs84 = df_geo.to_crs(epsg=4326) # 4326 is the EPSG code for WGS84\n", "print(df_geo.crs)\n", "print(df_wgs84.crs)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "...and **much** more... plus anything else that Pandas can do" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Super quick plotting for the web\n", "\n", "Here's a super simple map, which shows `Free` and `Fee-based` WiFi hotspots in NYC:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "ax = df_wgs84.plot() # This is all that's needed, but...\n", "# ...here's a hack to plot things a bit more nicely (GeoPandas is still new!)\n", "free = df_wgs84[\"type\"] == \"Free\" # Is it free?\n", "col = {True: \"green\", False: \"blue\"} # If free, green, otherwise blue\n", "for i, l in enumerate(ax.lines):\n", " l.set_markersize(6)\n", " l.set_color(col[free[i]])\n", "ax.axis('off') # Turn off axes\n", "plt.show()" ], "language": "python", "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Let's turn this map into a 'slippy' web-map" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import mplleaflet\n", "mplleaflet.display(fig=ax.figure, crs=df_wgs8.crs)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Want that as a standalone HTML page?" ] }, { "cell_type": "code", "collapsed": false, "input": [ "mplleaflet.show(fig=ax.figure, crs=df_wgs84.crs)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "#### Or perhaps you want to share something with others online? Use `geojson.io`.\n", "\n", "Note, your map should really be reprojected to EPSG:4326 (WGS84 lon/lat) for this to align properly." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import geojsonio\n", "res = geojsonio.display(boros.to_crs(epsg=4326).to_json(), force_gist=True)\n", "print(res)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Don't forget to pop on over to geojson.io and play around/edit your GeoJSON layer..." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Time to work on Notebook:\n", "\n", "[`Working with Vectors in Python`](../exercises/Working with Vectors in Python.ipynb)" ] } ], "metadata": {} } ] }