Quick Success Data Science

A friend approached me recently with an intriguing request: he wanted help selecting his Spring Break vacation destination in the Caribbean. His heart was set on aiding a region recently impacted by a Hurricane, hoping his tourism dollars would contribute to their recovery efforts. Naturally, he wanted to steer clear of areas affected too recently, so we decided to look at hurricanes from the past eight years (2017–2024) and exclude sites impacted in the last two (2023–2024).

Of course, an AI chatbot could’ve handled this in seconds, but I was not ready to go quietly into that good night and decided to perform the analysis myself using Python. Open-source hurricane data is readily available from multiple sources, including the:
- National Hurricane Center (NHC) Data Archive (HURDAT)
- International Best Track Archive for Climate Stewardship (IBTrACS)
- U.S. Geological Survey (USGS) Hurricanes Data
- NOAA Atlantic Oceanographic and Meteorological Laboratory (AOML)
Finding and prepping data is usually the hardest part of a data science project, so having this clean data ready was a godsend. Still, I wasn’t looking forward to starting. My past experiences with government data sources have been challenging. Extracting it is often a lot harder than it should be.
But then I discovered tropycal, a Python package that simplifies the retrieval and analysis of tropical cyclone data. Tropycal is a game-changer for anyone researching past storms or actively tracking current ones.
According to the docs, "Tropycal can read in HURDAT2 and IBTrACS reanalysis data and operational National Hurricane Center (NHC) Best Track data and conform them to the same format, which can be used to perform climatological, seasonal and individual storm analyses. For each storm, operational NHC and model forecasts, aircraft reconnaissance data, rainfall data, and any associated tornado activity can be retrieved and plotted."
Tropycal can produce both graphs and maps and you can easily convert extracted data into a pandas DataFrame for further analysis.
In this Quick Success Data Science project, we’ll use Tropycal to plot the tracks of Caribbean hurricanes from 2017 to 2024.
Installing Tropycal
You can find the Tropycal installation guide here.
The developers also recommend installing cartopy to leverage Tropycal’s plotting capabilities fully. Cartopy is a Python package for drawing maps.
The Code
The following code was written in JupyterLab and is described by cell.
Importing Libraries and Loading Data
The tropycal.tracks
module handles loading, filtering, and plotting hurricane tacks.
Tropycal can assess data from all over the world, so the next step is to choose a basin (in this case, north_atlantic
) and a data source. To handle storms in the current season, set the include_btk
argument to True
. This will read in preliminary best-track data from the NHC website, as HURDAT data is only available for completed seasons.
NOTE: Hurricane season in the North Atlantic is from June 1 to November 30.
import tropycal.tracks as tracks
# Load tracks; Set include_btk to True for current season data:
basin = tracks.TrackDataset(basin='north_atlantic',
source='hurdat',
include_btk=True)
This may take several seconds to run. You’ll see the progress in the output cell:
--> Starting to read in HURDAT2 data
--> Completed reading in HURDAT2 data (4.62 seconds)
--> Starting to read in best track data
--> Completed reading in best track data (17.2 seconds)
Filtering the Data to Categories and Years
Now we use the [filter_storms()](https://tropycal.github.io/tropycal/api/generated/tropycal.tracks.TrackDataset.filter_storms.html#trackdataset-filter-storms)
method to filter the basin
object by time interval and hurricane category. We’ll start with the 2017–2022 interval and look at hurricane categories 1 and higher.
# Filter N. Atlantic dataset to Category 1+ hurricanes for 2017-2022:
filtered_17_22 = basin.filter_storms(thresh={'v_min': 64},
year_range=(2017, 2022))
Tropycal does not appear to permit filtering using categories. Instead, it uses wind speeds in knots. For reference, here’s the Saffir-Simpson scale with sustained wind speeds in knots:
- Category 1: 64–82 knots
- Category 2: 83–95 knots
- Category 3: 96–112 knots
- Category 4: 113–136 knots
- Category 5: 137+ knots
To select Category 1 storms and higher, we’ll set the v_min
(velocity minimum) argument to 64
.
The filter_storms()
method returns a list of storm names. Next, we’ll pass this list to the plot_storms()
method.
Plotting the Hurricane Tracks for 2017–2022
Tropycal uses Matplotlib and cartopy to plot storms. This plotting functionality is encapsulated in the basin
object we made previously. To access it, we call its [plot_storms()](https://tropycal.github.io/tropycal/api/generated/tropycal.tracks.TrackDataset.plot_storms.html#tropycal.tracks.TrackDataset.plot_storms)
method.
# Plot tracks colored by category:
title = 'Caribbean Hurricanes (2017-2022)'
basin.plot_storms(storms=filtered_17_22,
title=title,
domain={'w':-89,'e':-54,'s':8,'n':25},
prop={'plot_names': False,
'dots': False,
'linecolor': 'category',
'linewidth': 1.0},
map_prop={'plot_gridlines': False});
For arguments, we pass our list of filtered storm names, a domain
, consisting of the lat-lon boundaries of the Caribbean Sea, and customization options (in dictionary format) such as turning off storm names, tracking dots, and lat-lon gridlines. Here’s the result:

The northeastern Caribbean suffered several devastating storms over this timeframe, including Irma and Maria in 2017.
To repeat the process for 2023–2024, we need to change the filtering criterion and plot title:
# Filter N. Atlantic dataset to hurricanes for 2023-2024:
filtered_23_24 = basin.filter_storms(thresh={'v_min': 64},
year_range=(2023, 2024))
# Plot tracks colored by category:
title = 'Caribbean Hurricanes (2023-2024)'
basin.plot_storms(storms=filtered_23_24,
title=title,
domain={'w':-89,'e':-54,'s':8,'n':25},
prop={'plot_names': False,
'dots': False,
'linecolor': 'category',
'linewidth': 1.0},
map_prop={'plot_gridlines': False});

You may have noticed that, while we requested hurricane tracks, some tracks are color-coded for non-hurricane events like tropical storms and depressions. This is because the track object includes the hurricane’s entire history, including its start as a tropical depression and end as a tropical (or non-tropical) storm.
Adjusting the Tracks to Capture Eyewall Width
The eyewall of a hurricane is the ring of towering thunderstorms surrounding the relatively calm and clear eye at the storm’s center. It contains the highest winds and most severe weather. North Atlantic hurricane eyewalls are generally 20–40 miles in width.
To capture this zone of severe weather on our map, we can use the properties dictionary to adjust the line width of the tracks to 11. This value yields a width of around 40 miles on the map. Here’s how it looks on the 2023–2024 data:
# Adjust track width to ~40 miles:
basin.plot_storms(storms=filtered_23_24,
title=title,
domain={'w':-89,'e':-54,'s':8,'n':25},
prop={'plot_names': False,
'dots': False,
'linecolor': 'category',
'linewidth': 11.0},
map_prop={'plot_gridlines': False});

Now we have a better idea of which destinations suffered the most devastation.
Unfortunately, there doesn’t seem to be a way to control the track’s transparency (alpha) value with Tropycal. If you have a lot of tracks, it’s better to adjust the dot size, as we do here with the 2017–2022 dataset:
# Plot tracks colored by category:
title = 'Caribbean Hurricanes (2017-2022)'
basin.plot_storms(storms=filtered_17_22,
title=title,
domain={'w':-89,'e':-54,'s':8,'n':25},
prop={'plot_names': False,
'ms': 13,
'linecolor': 'category',
'linewidth': 1.0},
map_prop={'plot_gridlines': False});

In this case, adding an argument for a marker size of 13 ('ms': 13
) yielded a dot approximately 40 miles in diameter.
AI Results
To check the results vs. AI, I gave Microsoft Copilot the following prompt: "What Caribbean vacation destinations have been most affected by hurricanes in the last 8 years (including 2024)?"
Copilot repeatedly returned erroneous results and couldn’t get it through its thick "head" that Hurricane Ivan was in 2004, not 2024. It also included hurricane events outside the requested range. While I found this concerning I was also gratified, as it justified doing the project myself!
My Results
Because we’ve confined our search to the areas near a hurricane’s eyewall, our maps should capture the hardest-hit areas in the Caribbean. That doesn’t mean other areas escaped devastation. Tropical storms can also cause significant damage, and severe weather can extend well beyond the eyewall vicinity.
Given the parameters we set at the beginning, the regions impacted by our 40-mile hurricane tracks in the 2023 and (ongoing) 2024 seasons include:
- Barbuda
- Grenada
- Grenadines
For the 2017–2022 seasons, the regions are:
- Barbuda
- St. Martin
- Anguilla
- St. Barthelemy
- Virgin Islands
- Puerto Rico
- The Dominican Republic (east coast)
- Cayman Islands
Summary
Well, that’s it! Thanks to the third-party Tropycal library, we sourced, filtered, and plotted official hurricane data with just a few lines of code. While we focused on the Caribbean Sea, keep in mind that Tropycal provides access to worldwide tropical cyclone data:

To help new users, the Tropycal docs include example scripts for multiple types of analyses. But be aware that, even with these, you may have trouble customizing your plots.
Like any user-friendly app, Tropycal makes difficult tasks easy at the expense of functionality. This high level of abstraction left me frustrated at times. Issues I struggled with included filtering based on storm categories, plotting country names, attractively plotting storm names, adjusting track colors, and setting alpha values on the track fill.
Despite this, Tropycal remains a tremendous resource to anyone working with tropical cyclone data. Not only does it include global storm track data as far back as 1851, but it also includes data on cyclone-related tornadoes and precipitation, as well as aircraft recon data.
Thanks!
Thanks for reading and please follow me for more Quick Success Data Science projects in the future.