Open In Colab

1.12. (Exercise) Hurricane Track Analysis#

376px-Florence_2018-09-11_1750Z.jpg

Can you quickly find out which US states hurricane Florence passed through using GeoPandas?

Image source: NASA Worldview

Tip

Installing GeoPandas

Please run the following code blocks in this section to:

  • Install the GeoPandas’s dependencies and GeoPandas

  • Download and unzip the data used in this notebook

  • Import GeoPandas and other required modules for the notebook

#Install GeoPandas' dependencies
!pip install --upgrade pyshp

!pip install --upgrade shapely

!pip install --upgrade descartes

!pip install --upgrade rtree
Requirement already satisfied: pyshp in /Users/itam/miniconda3/lib/python3.12/site-packages (3.0.2.post1)
Requirement already satisfied: shapely in /Users/itam/miniconda3/lib/python3.12/site-packages (2.1.2)
Requirement already satisfied: numpy>=1.21 in /Users/itam/miniconda3/lib/python3.12/site-packages (from shapely) (2.3.1)
Requirement already satisfied: descartes in /Users/itam/miniconda3/lib/python3.12/site-packages (1.1.0)
Requirement already satisfied: matplotlib in /Users/itam/miniconda3/lib/python3.12/site-packages (from descartes) (3.10.3)
Requirement already satisfied: contourpy>=1.0.1 in /Users/itam/miniconda3/lib/python3.12/site-packages (from matplotlib->descartes) (1.3.2)
Requirement already satisfied: cycler>=0.10 in /Users/itam/miniconda3/lib/python3.12/site-packages (from matplotlib->descartes) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in /Users/itam/miniconda3/lib/python3.12/site-packages (from matplotlib->descartes) (4.58.5)
Requirement already satisfied: kiwisolver>=1.3.1 in /Users/itam/miniconda3/lib/python3.12/site-packages (from matplotlib->descartes) (1.4.8)
Requirement already satisfied: numpy>=1.23 in /Users/itam/miniconda3/lib/python3.12/site-packages (from matplotlib->descartes) (2.3.1)
Requirement already satisfied: packaging>=20.0 in /Users/itam/miniconda3/lib/python3.12/site-packages (from matplotlib->descartes) (23.2)
Requirement already satisfied: pillow>=8 in /Users/itam/miniconda3/lib/python3.12/site-packages (from matplotlib->descartes) (11.3.0)
Requirement already satisfied: pyparsing>=2.3.1 in /Users/itam/miniconda3/lib/python3.12/site-packages (from matplotlib->descartes) (3.2.3)
Requirement already satisfied: python-dateutil>=2.7 in /Users/itam/miniconda3/lib/python3.12/site-packages (from matplotlib->descartes) (2.9.0.post0)
Requirement already satisfied: six>=1.5 in /Users/itam/miniconda3/lib/python3.12/site-packages (from python-dateutil>=2.7->matplotlib->descartes) (1.17.0)
Requirement already satisfied: rtree in /Users/itam/miniconda3/lib/python3.12/site-packages (1.4.1)
#Install GeoPandas
!pip install --upgrade geopandas
Collecting geopandas
  Using cached geopandas-1.1.1-py3-none-any.whl.metadata (2.3 kB)
Requirement already satisfied: numpy>=1.24 in /Users/itam/miniconda3/lib/python3.12/site-packages (from geopandas) (2.3.1)
Collecting pyogrio>=0.7.2 (from geopandas)
  Using cached pyogrio-0.11.1.tar.gz (287 kB)
  Installing build dependencies ... ?25l-
 \
 |
 /
 -
 done
?25h  Getting requirements to build wheel ... ?25l-
 done
?25h  Preparing metadata (pyproject.toml) ... ?25l-
 error
  error: subprocess-exited-with-error
  
  × Preparing metadata (pyproject.toml) did not run successfully.
   exit code: 1
  ╰─> [28 lines of output]
      Traceback (most recent call last):
        File "/Users/itam/miniconda3/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 353, in <module>
          main()
        File "/Users/itam/miniconda3/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 335, in main
          json_out['return_val'] = hook(**hook_input['kwargs'])
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/Users/itam/miniconda3/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 149, in prepare_metadata_for_build_wheel
          return hook(metadata_directory, config_settings)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/private/var/folders/7l/4c3bq00s0r994qdpmp2gfm6r0000gq/T/pip-build-env-her3mem8/overlay/lib/python3.12/site-packages/setuptools/build_meta.py", line 374, in prepare_metadata_for_build_wheel
          self.run_setup()
        File "/private/var/folders/7l/4c3bq00s0r994qdpmp2gfm6r0000gq/T/pip-build-env-her3mem8/overlay/lib/python3.12/site-packages/setuptools/build_meta.py", line 317, in run_setup
          exec(code, locals())
        File "<string>", line 154, in <module>
        File "<string>", line 129, in get_gdal_config
        File "<string>", line 85, in get_gdal_config
        File "<string>", line 39, in read_response
        File "/Users/itam/miniconda3/lib/python3.12/subprocess.py", line 466, in check_output
          return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/Users/itam/miniconda3/lib/python3.12/subprocess.py", line 548, in run
          with Popen(*popenargs, **kwargs) as process:
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/Users/itam/miniconda3/lib/python3.12/subprocess.py", line 1026, in __init__
          self._execute_child(args, executable, preexec_fn, close_fds,
        File "/Users/itam/miniconda3/lib/python3.12/subprocess.py", line 1953, in _execute_child
          raise child_exception_type(errno_num, err_msg, err_filename)
      FileNotFoundError: [Errno 2] No such file or directory: 'gdal-config'
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: metadata-generation-failed

× Encountered error while generating package metadata.
╰─> See above for output.

note: This is an issue with the package mentioned above, not pip.
hint: See above for details.
?25h
import pooch
# Download the data used in this notebook
data = pooch.retrieve('https://unils-my.sharepoint.com/:u:/g/personal/tom_beucler_unil_ch/EZQnP79VVtROtOlxw5QpfoYBtPG54sb4CZ2vzlg0bKkPew?download=1',
                          known_hash='200a740d0e448aa9e4e03d8a9965a70f228442a2da28d804c8e2337d0ef9749e',
                          processor=pooch.Unzip()
                          )
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[3], line 1
----> 1 import pooch
      2 # Download the data used in this notebook
      3 data = pooch.retrieve('https://unils-my.sharepoint.com/:u:/g/personal/tom_beucler_unil_ch/EZQnP79VVtROtOlxw5QpfoYBtPG54sb4CZ2vzlg0bKkPew?download=1',
      4                           known_hash='200a740d0e448aa9e4e03d8a9965a70f228442a2da28d804c8e2337d0ef9749e',
      5                           processor=pooch.Unzip()
      6                           )

ModuleNotFoundError: No module named 'pooch'
data
['/Users/itam/Library/Caches/pooch/3d43e48bb7d0d0370db00be3096108fe-EZQnP79VVtROtOlxw5QpfoYBtPG54sb4CZ2vzlg0bKkPew.unzip/florence.csv',
 '/Users/itam/Library/Caches/pooch/3d43e48bb7d0d0370db00be3096108fe-EZQnP79VVtROtOlxw5QpfoYBtPG54sb4CZ2vzlg0bKkPew.unzip/gz_2010_us_040_00_5m.json',
 '/Users/itam/Library/Caches/pooch/3d43e48bb7d0d0370db00be3096108fe-EZQnP79VVtROtOlxw5QpfoYBtPG54sb4CZ2vzlg0bKkPew.unzip/__MACOSX/._gz_2010_us_040_00_5m.json',
 '/Users/itam/Library/Caches/pooch/3d43e48bb7d0d0370db00be3096108fe-EZQnP79VVtROtOlxw5QpfoYBtPG54sb4CZ2vzlg0bKkPew.unzip/__MACOSX/._florence.csv']

References:

  1. Geopandas official website: Introduction to GeoPandas https://geopandas.org/en/stable/getting_started/introduction.html

  2. Automating GIS process https://autogis-site.readthedocs.io/en/latest/notebooks/L2/01-geopandas-basics.html

  3. Use Data for Earth and Environmental Science in Open Source Python https://www.earthdatascience.org/courses/use-data-open-source-python/

  4. The Shapely User Manual https://shapely.readthedocs.io/en/stable/manual.html

  5. Geospatial Analysis with Python and R https://kodu.ut.ee/~kmoch/geopython2020/index.html

  6. Introduction to Geospatial Data in Python https://www.datacamp.com/tutorial/geospatial-data-python

Exercise’s Instructions

  • Apply GeoPandas to read in the geospatial data, plot, and analyse the track of Hurricane Florence from August 30th to September 18th 2018.

  • Either write your own code, or fill in the blanks in the hidden cells 🙂

1.12.1. Q1) import geopandas, pandas#

#Import GeoPandas (as gpd), pandas, and matplotlib
# And ignore warnings
import warnings
warnings.filterwarnings('ignore')
#@markdown Fill in the blank code. Double-click here to reveal
#Import GeoPandas (as gpd), pandas, and matplotlib
import geopandas as gpd
import pandas as pd
import matplotlib.pyplot as plt

1.12.2. Q2) Read a Shapefile with GeoPandas’s read_file function#

# Find the index of the country file
countryindex = next(i for i, f in enumerate(data) if 'gz_2010_us_040_00_5m.json' in f)
# Find the index of the Florence cyclone
florenceindex = next(i for i, f in enumerate(data) if 'florence.csv' in f)
# Read data with the geopandas function
path = data[countryindex]
# Use geopandas to read the file and call it country
country = gpd.read_file(path)
#@markdown Fill in the blank code. Double-click here to reveal
# Read data with the geopandas function
path = data[0]
country = gpd.read_file(path)

1.12.3. Q3) Have a look at the data, what type of geometries does the data contain?#

# Print out the first few lines of the data
#@markdown Fill in the blank code. Double-click here to reveal
# The method to see the first few lines of the data
country.head()
GEO_ID STATE NAME LSAD CENSUSAREA geometry
0 0400000US01 01 Alabama 50645.326 MULTIPOLYGON (((-88.12466 30.28364, -88.08681 ...
1 0400000US02 02 Alaska 570640.950 MULTIPOLYGON (((-166.10574 53.98861, -166.0752...
2 0400000US04 04 Arizona 113594.084 POLYGON ((-112.53859 37.00067, -112.53454 37.0...
3 0400000US05 05 Arkansas 52035.477 POLYGON ((-94.04296 33.01922, -94.04304 33.079...
4 0400000US06 06 California 155779.220 MULTIPOLYGON (((-122.42144 37.86997, -122.4213...

1.12.4. Q4) Have a look at the data on a map using GeoPandas’s .plot() method. Exclude Alaska and Hawaii by the attribute ‘NAME’ and Pandas’s .isin() method. Specify the figsize to be 30 x 20.#

# Plot the US states (Alaska and Hawaii excluded)
#@markdown Fill in the blank code. Double-click here to reveal
# Plot the US states (Alaska and Hawaii excluded)
country[country[____].isin([____,____]) == False].____(figsize=(30,20))
data
['/Users/itam/Library/Caches/pooch/3d43e48bb7d0d0370db00be3096108fe-EZQnP79VVtROtOlxw5QpfoYBtPG54sb4CZ2vzlg0bKkPew.unzip/florence.csv',
 '/Users/itam/Library/Caches/pooch/3d43e48bb7d0d0370db00be3096108fe-EZQnP79VVtROtOlxw5QpfoYBtPG54sb4CZ2vzlg0bKkPew.unzip/gz_2010_us_040_00_5m.json',
 '/Users/itam/Library/Caches/pooch/3d43e48bb7d0d0370db00be3096108fe-EZQnP79VVtROtOlxw5QpfoYBtPG54sb4CZ2vzlg0bKkPew.unzip/__MACOSX/._gz_2010_us_040_00_5m.json',
 '/Users/itam/Library/Caches/pooch/3d43e48bb7d0d0370db00be3096108fe-EZQnP79VVtROtOlxw5QpfoYBtPG54sb4CZ2vzlg0bKkPew.unzip/__MACOSX/._florence.csv']
# Read in the hurricane florence data, change the longitude, and have a look at the hurricane florence dataframe
tc_path = data[florenceindex]
florence = pd.read_csv(tc_path)
florence = florence.drop(['AdvisoryNumber', 'Forecaster', 'Received'], axis=1)
florence['Long'] = 0 - florence['Long']
florence.head(3)
Date Lat Long Wind Pres Movement Type Name
0 08/30/2018 11:00 12.9 -18.4 30 1007 W at 12 MPH (280 deg) Potential Tropical Cyclone Six
1 08/30/2018 14:00 12.9 -19.0 30 1007 W at 12 MPH (280 deg) Potential Tropical Cyclone Six
2 08/30/2018 17:00 12.9 -19.4 30 1007 W at 9 MPH (280 deg) Potential Tropical Cyclone Six

1.12.5. Q5) Create a GeoDataFrame from florence DataFrame#

# Create a geodataframe from the hurricane florence dataframe
#@markdown Fill in the blank code. Double-click here to reveal
# Create a geodataframe from the hurricane florence dataframe
gdf_florence = gpd.____(florence, geometry=gpd.____(florence.Long, florence.Lat))
# Have a look at the hurricane geodataframe
gdf_florence.head(2)

1.12.6. Q6) Plot the US states map (without Alaska, Hawaii) and hurricane florence together#

# Plot to see the hurricane overlay over the US map

# And plot the hurricane position on top with red color to stand out:
#@markdown Fill in the blank code. Double-click here to reveal
# Plotting to see the hurricane overlay the US map:
fig, ax = plt.subplots(1, figsize=(30,20))
base = country[country[____].isin([____,____]) == False].____(ax=ax, color='#3B3C6E')

# plotting the hurricane position on top with red color to stand out:
gdf_florence.____(ax=base, color='darkred', marker="*", markersize=10)

1.12.7. Q7) What’s the coordinate reference system of the data?#

# Check the coordinate reference system of the geodataframe
#@markdown Fill in the blank code. Double-click here to reveal
# Check the coordinate reference system of the geodataframe
country.____

1.12.8. Q8) Which states are passed by the hurricane?#

Hint

One approach may be plot and see the trajectory of the hurricane on the US map. Other approaches are more than welcome.

# Plot the US states without Alaska and Hawaii, then
#  Annotate the US states with their names, then
# Select the hurricane trajectory points inside the US boundary with the overlay operation, then
# Plot the hurricane trajectory inside US boundary
#@markdown Fill in the blank code. Double-click here to reveal
# Plot the US states without Alaska and Hawaii
df = country[country[____].isin([____,____]) == False]
ax = df.plot(figsize=(30,20))
#  Annotate the US states with their names
_ = df.apply(lambda x: ax.____(s=x['NAME'], xy=x.geometry.centroid.coords[0], ha='center'), axis=1)
# Select the hurricane trajectory points inside the US boundary with the overlay operation
res_intersection = gdf_florence.____(country, how='intersection')
# Plot the hurricane trajectory inside US boundary
____.plot(ax=ax, color='red', marker="*", markersize=25)