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
foliumandgeopandaslibraries 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
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_staticis used to display the map only.st_foliumis 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:
we need coordinates
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
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.
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
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')
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
load the data into pandas
load the geometry data into geopandas (in the data folder)
merge the data on a common key
explore in geopandas!