6-3: Visualizations: maps#

  • mapping with folium and geopandas

Mapping#

  • Mapping is a powerful way to visualize data. You can place points on a map, draw lines, and shade areas.

  • In this lesson, we will use the folium and geopandas libraries to create maps.

Map Visualizations with Folium#

To create map visualizations, we will use the Folium, which is a Python wrapper for the Leaflet.js library.

https://python-visualization.github.io/folium/latest/

Folium uses https://www.openstreetmap.org/ for drawing maps. Its a free/open source alternative to a service like Google Maps.

1import folium
2JMA = (43.0362, -76.1363)
3map1 = folium.Map(location=JMA, zoom_start=18)
4jma_marker = folium.Marker(JMA, popup='JMA Wireless Dome', tooltip="JMA").add_to(map1)
5map1
Make this Notebook Trusted to load map: File -> Trust Notebook

Folium and Streamlit#

To display folium maps to display in Streamlit, you need to use the streamlit_folium module.

This module has two functions:

  • folium_static is used to display the map only.

  • st_folium is use to display the map and return data while the user interacts with the map.

See: 6-3-st-folium.py

Map Markers Colors and Icons#

Through the icon named argument you can assign an icon to the popup. You must create a folium.Icon() to assign a custom icon. There are three named arguments:

color= the color of the marker icon_color= the color of the icon on the marker icon= the name of the icon.

Valid colors are: ['red', 'blue', 'green', 'purple', 'orange', 'darkred', 'lightred', 'beige', 'darkblue', 'darkgreen', 'cadetblue', 'darkpurple', 'white', 'pink', 'lightblue', 'lightgreen', 'gray', 'black', 'lightgray']

Valid icons can be found here: https://fontawesome.com/v4/icons/ Your mileage may vary here as not all the icons listed are available.

Mapping a dataframe#

To map a dataframe:

  1. we need coordinates

  2. we need to use loop over the data, creating a marker for each row

 1import pandas as pd
 2classesdf = pd.read_csv("https://raw.githubusercontent.com/mafudge/datasets/master/delimited/class-schedule.csv")
 3schine = (43.03986, -76.13375)
 4m = folium.Map(location=schine, zoom_start=17)
 5
 6for index, row in classesdf.iterrows():
 7    text = f"{row['Course']} {row['Day']} {row['Time']} {row['Building']}"
 8    dd = (row['Lat'], row['Lon'])
 9    if row['Day'] == "TuTh":
10        markercolor = 'orange'
11    else:
12        markercolor = 'darkblue'
13    marker = folium.Marker(location=dd, popup=text, icon = folium.Icon(color = markercolor, icon="globe"))
14    marker.add_to(m)
15
16m
Make this Notebook Trusted to load map: File -> Trust Notebook

Challenge 6-3-1#

Streamlit version of Parkmagic!

Load in the final_cuse_parking_violations.csv in the data folder and create a map of the parking violations in Syracuse.

  • drop rows without a latitude and longitude

  • provide a dropdown to select the status of the violation

  • place pins on the map with the street name and the violation description

  • color code the pins based on day of the week

  • to make the map more readable take a random sample of 50 rows from the dataframe

Geopandas#

Geopandas is a library that extends the Pandas library to work with geospatial data. It is built on top of the Shapely, Fiona, and Matplotlib libraries.

https://geopandas.org/

Geopandas can read and write data in many formats, including shapefiles, GeoJSON, and PostGIS. It can also display data on a map.

Geopandas adds a geometry column to the dataframe. This column contains the geometry of the object. The geometry can be a POINT, LINE, or PLOYGON.

Geopandas as a built in explore() function to display the data on a map.

1import folium
2import geopandas as gpd
3schine = (43.03986, -76.13375)
4map = folium.Map(location=schine, zoom_start=17)
5classesdf = pd.read_csv("https://raw.githubusercontent.com/mafudge/datasets/master/delimited/class-schedule.csv")
6gdf = gpd.GeoDataFrame(classesdf, geometry=gpd.points_from_xy(classesdf['Lon'], classesdf['Lat']))
7gdf
Course Day Time Building Room Lat Lon geometry
0 IST256 M 3:45pm HBC Gifford 43.03819 -76.13413 POINT (-76.13413 43.03819)
1 MAT221 TuTh 12:45pm Bowne 104 43.03674 -76.13320 POINT (-76.1332 43.03674)
2 WRT206 MW 9:20am Crouse 111 43.03852 -76.13676 POINT (-76.13676 43.03852)
3 COM222 TuTh 9:20am NH II 232 43.04020 -76.13521 POINT (-76.13521 43.0402)
4 IST343 MW 2:15pm Hinds 243 43.03834 -76.13364 POINT (-76.13364 43.03834)
1map_out = gdf.explore(m=map, marker_type="marker")
2map_out
Make this Notebook Trusted to load map: File -> Trust Notebook

Choropleth Maps in Geopandas#

A choropleth map is a map that uses shading to represent the value of a variable. The shading can be based on a single value or a range of values.

Choropleths maps require a GeoDataFrame with a geometry column. The geometry column contains the shapes that will be displayed on the map.

1from matplotlib import colormaps
2print(list(colormaps))
['magma', 'inferno', 'plasma', 'viridis', 'cividis', 'twilight', 'twilight_shifted', 'turbo', 'Blues', 'BrBG', 'BuGn', 'BuPu', 'CMRmap', 'GnBu', 'Greens', 'Greys', 'OrRd', 'Oranges', 'PRGn', 'PiYG', 'PuBu', 'PuBuGn', 'PuOr', 'PuRd', 'Purples', 'RdBu', 'RdGy', 'RdPu', 'RdYlBu', 'RdYlGn', 'Reds', 'Spectral', 'Wistia', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd', 'afmhot', 'autumn', 'binary', 'bone', 'brg', 'bwr', 'cool', 'coolwarm', 'copper', 'cubehelix', 'flag', 'gist_earth', 'gist_gray', 'gist_heat', 'gist_ncar', 'gist_rainbow', 'gist_stern', 'gist_yarg', 'gnuplot', 'gnuplot2', 'gray', 'hot', 'hsv', 'jet', 'nipy_spectral', 'ocean', 'pink', 'prism', 'rainbow', 'seismic', 'spring', 'summer', 'terrain', 'winter', 'Accent', 'Dark2', 'Paired', 'Pastel1', 'Pastel2', 'Set1', 'Set2', 'Set3', 'tab10', 'tab20', 'tab20b', 'tab20c', 'grey', 'gist_grey', 'gist_yerg', 'Grays', 'magma_r', 'inferno_r', 'plasma_r', 'viridis_r', 'cividis_r', 'twilight_r', 'twilight_shifted_r', 'turbo_r', 'Blues_r', 'BrBG_r', 'BuGn_r', 'BuPu_r', 'CMRmap_r', 'GnBu_r', 'Greens_r', 'Greys_r', 'OrRd_r', 'Oranges_r', 'PRGn_r', 'PiYG_r', 'PuBu_r', 'PuBuGn_r', 'PuOr_r', 'PuRd_r', 'Purples_r', 'RdBu_r', 'RdGy_r', 'RdPu_r', 'RdYlBu_r', 'RdYlGn_r', 'Reds_r', 'Spectral_r', 'Wistia_r', 'YlGn_r', 'YlGnBu_r', 'YlOrBr_r', 'YlOrRd_r', 'afmhot_r', 'autumn_r', 'binary_r', 'bone_r', 'brg_r', 'bwr_r', 'cool_r', 'coolwarm_r', 'copper_r', 'cubehelix_r', 'flag_r', 'gist_earth_r', 'gist_gray_r', 'gist_heat_r', 'gist_ncar_r', 'gist_rainbow_r', 'gist_stern_r', 'gist_yarg_r', 'gnuplot_r', 'gnuplot2_r', 'gray_r', 'hot_r', 'hsv_r', 'jet_r', 'nipy_spectral_r', 'ocean_r', 'pink_r', 'prism_r', 'rainbow_r', 'seismic_r', 'spring_r', 'summer_r', 'terrain_r', 'winter_r', 'Accent_r', 'Dark2_r', 'Paired_r', 'Pastel1_r', 'Pastel2_r', 'Set1_r', 'Set2_r', 'Set3_r', 'tab10_r', 'tab20_r', 'tab20b_r', 'tab20c_r']
1import random
2gdf = gpd.read_file("./data/stlucia.geojson")
3gdf['Amount'] = gdf.apply(lambda row: random.randint(50,500), axis=1)
4gdf
source id name geometry Amount
0 https://simplemaps.com LC06 Gros Islet POLYGON ((-60.97997 14.04352, -60.97606 14.061... 344
1 https://simplemaps.com LC02 Castries POLYGON ((-60.97997 14.04352, -60.96559 14.034... 155
2 https://simplemaps.com LC01 Anse-la-Raye POLYGON ((-61.0266 13.98737, -61.00945 13.9817... 237
3 https://simplemaps.com LC10 Soufrière POLYGON ((-60.98063 13.8928, -60.97185 13.8827... 211
4 https://simplemaps.com LC03 Choiseul POLYGON ((-61.0681 13.79218, -61.04956 13.8063... 366
5 https://simplemaps.com LC07 Laborie POLYGON ((-61.01892 13.75625, -61.01203 13.770... 445
6 https://simplemaps.com LC11 Vieux Fort POLYGON ((-60.98158 13.83577, -60.97522 13.839... 381
7 https://simplemaps.com LC08 Micoud POLYGON ((-60.97522 13.83923, -60.96433 13.845... 475
8 https://simplemaps.com LC09 Praslin POLYGON ((-60.96057 13.87901, -60.96057 13.900... 419
9 https://simplemaps.com LC05 Dennery POLYGON ((-60.96057 13.90032, -60.95681 13.927... 224
10 https://simplemaps.com LC04 Dauphin POLYGON ((-60.93559 14.01796, -60.933 14.03692... 97
1gdf.explore(column='Amount', cmap='inferno')
Make this Notebook Trusted to load map: File -> Trust Notebook

Geopandas Choropleth Maps in streamlit.#

If you plan to use GeoDataFrame.explore() then you will need to call folium_static() from the streamlit_folium module to display the map in Streamlit.

6-3-geopandas-px-mapbox.py

Challenge 6-3-2#

Plot the following data as a choropleth map:

https://raw.githubusercontent.com/wrobstory/vincent/master/examples/data/US_Unemployment_Oct2012.csv

  1. load the data into pandas

  2. load the geometry data into geopandas (in the data folder)

  3. merge the data on a common key

  4. explore in geopandas!