Analyze Earthquake Data with Python
Fetch live USGS earthquake data and visualize global seismic patterns.
Introduction
30 Second Summary
Every day, thousands of earthquakes ripple across the planet. Most go unnoticed, but the data they leave behind tells a powerful story about where and how the Earth moves.
In this project, you will pull live earthquake data from a government API, clean and transform it with Python, and create visualizations that reveal global seismic patterns.
What You'll Build
When you run your finished Jupyter Notebook, you see three charts that transform live government earthquake data into a visual story of where, when, and how powerfully the Earth shakes.
By the end of this project, you'll have:
- Pull thousands of live earthquake records from the USGS Earthquake API straight into your notebook, with no API key or signup required.
- Flatten nested GeoJSON into a clean pandas DataFrame with readable column names and proper data types.
- Generate three styled matplotlib charts that reveal magnitude distributions, depth patterns, and global earthquake hotspots.
- Secret Mission: Filter earthquakes to a specific geographic region and build a daily frequency time-series chart showing earthquake activity over time.
Are there any prerequisites?
You'll need Python and VS Code installed on your computer before starting. Some coding experience is helpful, but no data science background is required.
Before We Start
Before We Start...
Before we dive in, let's lock in what you're about to build and why it matters.
You're about to pull live earthquake data from a government API, wrangle it into shape, and turn it into charts that reveal real patterns in global seismic activity.
Set Up Your Data Science Environment
Before you can pull earthquake data and build charts, you need the right tools inside VS Code. A Jupyter Notebook lets you write and run Python code in small, testable chunks called cells. It is the standard workspace for data science work.
In this step, you will install two VS Code extensions, four Python libraries, and create your first notebook. By the end, you will have a confirmed working environment ready for analysis.
In this step, get ready to:
- Install the Python and Jupyter extensions in VS Code.
- Install pandas, matplotlib, requests, and ipykernel with pip.
- Create a Jupyter Notebook and verify your Python kernel works.
Install the Python and Jupyter extensions
VS Code does not understand Jupyter Notebooks or Python code out of the box. Two extensions add that support.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type VS Code and press Enter to open it.
- Open the Extensions view by pressing Cmd+Shift+X (macOS) or Ctrl+Shift+X (Windows).
- Type Python in the search bar.
- Find the extension named Python by Microsoft (the extension ID is ms-python.python).
- Click Install.
- Clear the search bar and type Jupyter.
- Find the extension named Jupyter by Microsoft (the extension ID is ms-toolsai.jupyter).
- Click Install.
Both extensions now show as installed in the Extensions sidebar. The Python extension gives VS Code code intelligence for Python files. The Jupyter extension lets VS Code open and run notebook files.
Why do you need ipykernel separately?
The Jupyter extension handles the notebook interface inside VS Code. However, it does not include a Python kernel to run your code.
The ipykernel package is what actually launches a Python process behind the scenes when you press Run on a cell. You will install it in the next substep.
Extension not appearing in search results?
- Make sure you are searching in the Extensions view (the square icon in the left sidebar), not the main editor search.
- Check that you are searching for Python or Jupyter exactly. The Microsoft-published one should appear at the top.
- Still stuck? Help me find and install the Python and Jupyter extensions in VS Code.
Install your Python libraries
Your notebook will rely on four Python libraries. Each one handles a different part of the data science workflow.
- Open the VS Code integrated terminal by pressing Ctrl+`.
- Install all four libraries by running this command:
pip install pandas matplotlib requests ipykernel
What does each library do?
- pandas organizes data into tables called DataFrames. You will use it to clean and transform the earthquake data.
- matplotlib creates charts and visualizations. You will use it to plot histograms, scatter plots, and maps.
- requests sends HTTP requests to web APIs. You will use it to fetch live earthquake data from the USGS.
- ipykernel lets VS Code launch a Python process to run your notebook cells.
- Wait for the installation to finish. You should see Successfully installed followed by the package names near the bottom of the terminal output.
Pip command not working?
- On macOS, pip sometimes needs to be called as pip3. Try running the command with pip3 instead.
- If you see a permissions error, try adding --user to the end of the command. This installs the packages for your user account only.
- Still stuck? Help me install pandas, matplotlib, requests, and ipykernel with pip.
Create your Jupyter Notebook and verify your setup
With the extensions and libraries installed, you can now create the notebook file that will hold all of your earthquake analysis code.
- Open the Command Palette by pressing Cmd+Shift+P (macOS) or Ctrl+Shift+P (Windows).
- Type Create: New Jupyter Notebook and select it from the dropdown.
A new untitled notebook opens in the editor with a blank code cell.
- Save the file by pressing Cmd+S (macOS) or Ctrl+S (Windows).
- Choose a location on your Desktop and name the file earthquake_analysis.ipynb.
- Click Select Kernel in the top-right corner of the notebook.
- Choose Python Environments.
- Select your Python installation from the list. After selecting, the kernel name appears in the top-right corner of the notebook.
What is a kernel?
A kernel is the process that actually runs your code. When you click the play button on a notebook cell, VS Code sends the code to the kernel, which executes it and sends the results back. Selecting a Python kernel tells VS Code which Python installation to use.
Now it is time to prove everything works. Before you run this test, what do you think will happen if pandas installed correctly?
- Click inside the empty code cell in your notebook and type the following code:
import pandas as pd
print(pd.__version__)
- Click the play button to the left of the cell (or press Shift+Enter) to run it.
A version number appears directly below the cell. This confirms that pandas is installed, the kernel is connected, and your notebook is ready to go.
No output or seeing an error?
- If the cell hangs with no output, check that you selected a kernel in the top-right corner. A notebook cannot run code without a kernel connected.
- If you see a ModuleNotFoundError, the kernel may be using a different Python than the one you installed the libraries into. Click the kernel name in the top-right corner and switch to the Python environment where you ran pip install.
- If VS Code asks to install ipykernel, click Install in the prompt. This means the kernel could not find the package you installed earlier.
- Still stuck? Help me get my Jupyter Notebook cell to run in VS Code.
- Delete the test cell by clicking on it, then clicking the trash can icon to its right. You will start writing real analysis code in the next step.
Your data science environment is locked and loaded. Next up, you will use it to pull live earthquake data from a government API and get your first look at what seismic data actually looks like.
Pull Live Earthquake Data from the USGS API
Your notebook is connected and your libraries are installed. Every data science project starts with raw data, and right now your notebook has none.
The USGS Earthquake Catalog API provides live seismic data from around the world with no authentication required. In this step, you'll pull 30 days of earthquake records into your notebook and inspect the raw GeoJSON data structure the API returns.
In this step, get ready to:
- Import the libraries you'll use throughout the project.
- Fetch 30 days of earthquake data from the USGS API.
- Inspect the nested GeoJSON data structure.
Fetch earthquake data from the USGS API
Before you can call any API, you need to import the tools your notebook will use. You'll use four libraries: requests for HTTP calls, pandas for data manipulation, matplotlib for charts, and Python's built-in datetime for working with dates.
- Add the following code to the first cell of your earthquake_analysis.ipynb notebook:
# HTTP requests to call the USGS API
import requests
# Data manipulation and analysis
import pandas as pd
# Chart and visualization library
import matplotlib.pyplot as plt
# Date utilities for calculating the 30-day window
from datetime import datetime, timedelta
What does this code do?
- requests lets you send HTTP requests to web APIs and get data back.
- pandas as pd gives you DataFrames for organizing data into rows and columns.
- matplotlib.pyplot as plt provides the charting functions you'll use for visualization.
- datetime and timedelta let you calculate dates like "30 days ago" for the API query.
- Run the cell by pressing Shift+Enter.
- The execution counter to the left of the cell updates to [1], confirming your imports loaded without errors.
Seeing a ModuleNotFoundError?
This means one of the libraries is not installed in the Python environment your kernel is using.
- Switch to your VS Code terminal and re-run pip install pandas matplotlib requests ipykernel.
- Make sure the kernel selected in the top-right corner of the notebook matches the Python environment you installed the libraries into.
- help me fix a ModuleNotFoundError in my Jupyter Notebook
Now for the exciting part. You'll call the USGS Earthquake Catalog API and pull every earthquake above magnitude 1.0 from the last 30 days.
Before you run the next cell, what do you think the API will return for a successful call? What HTTP status code would you expect?
- Create a new cell below by clicking the + Code button at the top of the notebook, then add the following code:
# Calculate the date range: today minus 30 days
end_time = datetime.utcnow()
start_time = end_time - timedelta(days=30)
# Set up query parameters for the USGS API
params = {
"format": "geojson",
"starttime": start_time.strftime("%Y-%m-%d"),
"endtime": end_time.strftime("%Y-%m-%d"),
"minmagnitude": 1.0,
}
# Send the GET request to the USGS Earthquake Catalog API
response = requests.get(
"https://earthquake.usgs.gov/fdsnws/event/1/query",
params=params,
)
print(f"Status code: {response.status_code}")
# Parse the JSON response and preview the first earthquake
data = response.json()
print(f"Fetched {data['metadata']['count']:,} earthquakes")
print(f"\nFirst earthquake properties:\n{data['features'][0]['properties']}")
What does this code do?
- datetime.utcnow() gets today's date in UTC (the timezone the USGS API uses). timedelta(days=30) subtracts 30 days to set the start of your date window.
- The params dictionary tells the API to return GeoJSON format, filter to your 30-day window, and exclude earthquakes below magnitude 1.0.
- requests.get() sends the HTTP request to the USGS API endpoint. The status code confirms whether the request succeeded.
- response.json() parses the raw text into a Python dictionary. The metadata count field tells you how many earthquakes matched your query.
- Run the cell by pressing Shift+Enter.
- You should see three lines of output: Status code: 200, a count like Fetched 9,583 earthquakes, and a dictionary showing the first earthquake's properties (magnitude, place, time, and more).
Why does my count look different?
The earthquake count changes every time you run this cell because the API returns live data. Your number will differ from anyone else's. The exact count does not matter. What matters is that you got a 200 status code and a non-zero count.
Not seeing Status code: 200?
- If you see a ConnectionError, check that your computer is connected to the internet.
- If you see a NameError for requests or datetime, go back to Cell 1 and re-run it first. Jupyter cells must run in order.
- If you see a status code like 400, double-check that the parameter names match exactly: format, starttime, endtime, minmagnitude.
- help me debug my USGS API request
Examine the nested GeoJSON structure
The properties dictionary you just printed contains magnitude, place, and time. But earthquake location (longitude, latitude, depth) is stored in a separate geometry field. This split is the data-wrangling challenge you'll solve in the next step.
- Create a new cell below and print the geometry of the first earthquake by adding this code:
# Inspect the geometry structure to see how coordinates are stored
print(f"First earthquake geometry:\n{data['features'][0]['geometry']}")
What does this output tell you?
The geometry dictionary contains a coordinates list with three numbers: [longitude, latitude, depth]. The USGS uses this GeoJSON convention where longitude comes before latitude.
This is the core problem. The data you need for analysis is split across properties (magnitude, place, time) and geometry (location coordinates). A pandas DataFrame needs all of this in one flat table. You cannot pass this nested structure directly to pd.DataFrame().
- Run the cell by pressing Shift+Enter.
- You should see a dictionary with a type of Point and a coordinates list containing three numbers (longitude, latitude, depth).
✔️ Awesome, I've got everything!
Double check you've saved your notebook. You should have three cells that all ran successfully with output below Cells 2 and 3.
ⓧ I'd like to double check the full code
Your notebook should have three cells in this order. Scroll up and confirm each one is present and matches what you typed.
- Cell 1: Imports for requests, pandas, matplotlib.pyplot, datetime, and timedelta. No output when run.
- Cell 2: Calculates the 30-day date range, builds the params dictionary, calls requests.get(), and prints the status code, earthquake count, and first feature's properties.
- Cell 3: Prints the first feature's geometry dictionary showing the coordinates list.
You've got thousands of real earthquake records sitting in your notebook. Next up, you'll flatten that nested GeoJSON into a clean pandas DataFrame you can actually analyze.
Build a Clean DataFrame
In the previous step, you fetched live earthquake data from the USGS API and inspected its nested GeoJSON structure.
You saw that earthquake properties like magnitude and place sit in one dictionary, while coordinates hide inside a separate geometry object. pandas needs flat, tabular data where each row is one earthquake and each column is one field. In this step, you will flatten that nested structure into a clean DataFrame ready for analysis.
In this step, get ready to:
- Flatten nested GeoJSON features into a pandas DataFrame.
- Convert timestamps and drop unnecessary columns to produce a clean dataset.
Flatten the GeoJSON into a DataFrame
Right now, your earthquake data is locked inside a deeply nested structure. Each feature stores its properties (magnitude, place, time) in one dictionary and its coordinates (longitude, latitude, depth) in another.
To get all of this into a single flat row, you need to loop through every feature, merge the properties with the coordinates, and collect the results into a list that pandas can convert into a table.
- Create a new cell below Cell 3 in earthquake_analysis.ipynb and paste the following code:
# Loop through each earthquake feature and flatten the nested structure
rows = []
for feature in data["features"]:
# Copy all properties (mag, place, time, etc.) as the base row
row = feature["properties"].copy()
# Extract coordinates from the nested geometry object
coords = feature["geometry"]["coordinates"]
row["longitude"] = coords[0]
row["latitude"] = coords[1]
row["depth"] = coords[2]
rows.append(row)
# Create a DataFrame from the flattened list of dictionaries
df = pd.DataFrame(rows)
print(f"DataFrame shape: {df.shape}")
df.head()
What does this code do?
- feature["properties"].copy() grabs the flat property dictionary (magnitude, place, time, and more) for each earthquake. The .copy() prevents modifying the original data.
- feature["geometry"]["coordinates"] pulls the coordinate list, which stores values in the order [longitude, latitude, depth]. Each value is assigned to its own named key in the row.
- pd.DataFrame(rows) converts the list of flat dictionaries into a tabular DataFrame, with one row per earthquake.
- Run the cell by pressing Shift+Enter.
- You should see the DataFrame shape printed (the first number matches the earthquake count from Step 2) and a table showing the first 5 rows with columns like mag, place, time, longitude, latitude, and depth.
Seeing a NameError for data?
This means the data variable does not exist in memory. Go back to Cell 2 and re-run it (Shift+Enter) to fetch the earthquake data again. Then re-run this cell.
Help me fix my NameError in the earthquake notebook.
Convert data types and clean up columns
The DataFrame has all your earthquake data, but it is not quite analysis-ready. The time column is still stored as raw Unix milliseconds, which is an unreadable integer. Several columns like tz, url, and detail are metadata that add noise without helping your analysis.
- Create a new cell below Cell 4 and paste the following code:
# Convert Unix milliseconds to readable datetime
df["time"] = pd.to_datetime(df["time"], unit="ms")
# Remove columns that aren't useful for analysis
columns_to_drop = [
"tz", "updated", "detail", "url", "ids", "sources",
"types", "nst", "dmin", "rms", "gap", "net", "code",
]
df = df.drop(columns=[c for c in columns_to_drop if c in df.columns])
# Verify the cleaned DataFrame's structure
df.info()
What does this code do?
- pd.to_datetime(df["time"], unit="ms") converts the raw integer timestamps into human-readable dates. The unit="ms" tells pandas the numbers are in milliseconds.
- columns_to_drop lists 13 columns that carry metadata or identifiers you do not need for magnitude, location, or time analysis.
- The list comprehension [c for c in columns_to_drop if c in df.columns] safely skips any column that does not exist, preventing errors if the API response changes.
- df.info() prints every column's name, data type, and non-null count so you can confirm the cleanup worked.
Before you run this cell, what do you expect to see? Think about which columns should remain and what the time column's data type should now be.
- Run the cell by pressing Shift+Enter.
You should see a summary listing columns like mag, place, time, longitude, latitude, and depth. The time column should now show datetime64[ns] as its data type instead of int64. The total number of rows should match the earthquake count from Step 2.
Seeing a KeyError when dropping columns?
If you modified the columns_to_drop list and added a column name that is not in the DataFrame without the list comprehension guard, pandas will raise a KeyError. Make sure your df.drop() line uses the list comprehension exactly as shown above.
Help me fix a KeyError when cleaning my earthquake DataFrame.
✔️ Awesome, I've got everything!
Great. Double check you have saved earthquake_analysis.ipynb.
ⓧ I'd like to double check the full code
Your notebook should now have 5 cells. Scroll through your notebook and confirm these cells are present in order:
- Cell 1: Imports (requests, pandas, matplotlib, datetime).
- Cell 2: API request to the USGS endpoint, printing the status code, earthquake count, and first feature's properties.
- Cell 3: Print the first feature's geometry dictionary.
- Cell 4: Loop through features, flatten properties and coordinates into rows, create df with pd.DataFrame(rows), print shape, and display .head().
- Cell 5: Convert time to datetime, drop 13 unnecessary columns, and call df.info().
Your raw earthquake data is now a clean, analysis-ready DataFrame. Next up, you will turn those rows and columns into visualizations that reveal real patterns in global seismic activity.
Explore and Visualize the Data
Your DataFrame is clean, typed, and ready for analysis. Every earthquake from the past 30 days sits in a tidy row with its magnitude, location, and depth.
But a table of thousands of rows can't reveal patterns on its own. In this step, you'll use matplotlib to build three charts that transform your earthquake data into visual stories.
In this step, get ready to:
- Create a magnitude histogram to see the distribution of earthquake strengths.
- Style your charts with titles, labels, colors, and build a depth-vs-magnitude scatter plot.
- Build a geographic scatter plot that reveals tectonic plate boundaries from earthquake locations alone.
Create a basic magnitude histogram
A histogram groups continuous values into bins and counts how many data points fall in each range. It's the first chart a data scientist reaches for to understand the shape of their data.
- Create a new cell below Cell 5 in your notebook and paste this code:
plt.figure(figsize=(10, 6))
plt.hist(df["mag"].dropna(), bins=30)
plt.show()
What does this code do?
- plt.figure(figsize=(10, 6)) creates a 10-by-6 inch canvas for the chart.
- plt.hist() groups the magnitude values into 30 bins and counts how many earthquakes fall in each range.
- .dropna() removes any missing magnitude values so the histogram doesn't error out.
Before you run this cell, what do you think the histogram will look like? Will it be ready to share with a colleague?
- Run the cell by pressing Shift+Enter.
A histogram appears showing earthquake magnitudes grouped into 30 bins. But take a closer look. There is no title explaining what this chart shows. There are no axis labels identifying the axes. The colors are matplotlib's generic default. The chart is technically correct, but it tells no story.
That's exactly the gap you'll close next.
Seeing a NameError instead of a chart?
- If you see NameError: name 'plt' is not defined, go back to Cell 1 and run it first. That cell imports matplotlib.
- If you see NameError: name 'df' is not defined, run Cells 2 through 5 in order. The DataFrame is built across those cells.
- help me debug my histogram cell
Style the histogram and build a scatter plot
The unstyled histogram proved that your data works. Now you'll add the polish that turns it into something readable and create a second chart to explore a different relationship in the data.
- Create a new cell below Cell 6 and paste this improved histogram code:
plt.figure(figsize=(10, 6))
plt.hist(df["mag"].dropna(), bins=30, color="steelblue", edgecolor="black")
plt.title("Distribution of Earthquake Magnitudes (Past 30 Days)", fontsize=14)
plt.xlabel("Magnitude", fontsize=12)
plt.ylabel("Number of Earthquakes", fontsize=12)
plt.grid(axis="y", alpha=0.3)
plt.tight_layout()
plt.show()
What changed from the unstyled version?
- color="steelblue" and edgecolor="black" make each bar visually distinct instead of blending together.
- plt.title(), plt.xlabel(), and plt.ylabel() tell the viewer exactly what they're looking at without needing to guess.
- plt.grid(axis="y", alpha=0.3) adds faint horizontal gridlines so you can read bar heights accurately.
- plt.tight_layout() adjusts spacing so labels and titles don't get clipped at the edges.
- Run the cell by pressing Shift+Enter.
You should see a histogram with steelblue bars, black edges, a clear title reading "Distribution of Earthquake Magnitudes (Past 30 Days)", and labeled axes. Compare it to Cell 6's output above. Same data, completely different impact.
Chart looks the same as before?
- Make sure you created a new Cell 7 and pasted the updated code there. If you replaced Cell 6, re-paste the original unstyled code into Cell 6 and put the styled version in a new cell below it.
- Check that you ran the new cell, not the old one. Look for the output appearing directly below the styled code.
- help me fix my styled histogram
Now you'll build a scatter plot that explores the relationship between earthquake depth and magnitude. Do deeper earthquakes tend to be stronger?
- Create a new cell below Cell 7 and paste this scatter plot code:
plt.figure(figsize=(10, 6))
scatter = plt.scatter(
df["depth"],
df["mag"],
c=df["mag"],
cmap="coolwarm",
s=df["mag"] ** 2 * 5,
alpha=0.5,
edgecolors="none",
)
plt.colorbar(scatter, label="Magnitude")
plt.title("Earthquake Depth vs Magnitude", fontsize=14)
plt.xlabel("Depth (km)", fontsize=12)
plt.ylabel("Magnitude", fontsize=12)
plt.grid(alpha=0.3)
plt.tight_layout()
plt.show()
What does this scatter plot show?
- Each earthquake becomes a dot, with depth on the x-axis and magnitude on the y-axis.
- c=df["mag"] colors each dot by magnitude, and cmap="coolwarm" assigns a blue-to-red gradient so weaker earthquakes are blue and stronger ones are red.
- s=df["mag"] ** 2 * 5 sizes each dot proportionally to magnitude squared, making stronger earthquakes visually larger.
- plt.colorbar() adds a color legend on the side so you can read what each color means.
- Run the cell by pressing Shift+Enter.
You should see a scatter plot with dots sized and colored by magnitude. Look for patterns. Most earthquakes cluster at shallow depths and lower magnitudes, with a few large red dots standing out.
Seeing a warning about NaN values?
- Some earthquakes may have missing magnitude or depth values. The scatter plot still renders, but you may see a matplotlib warning. This is normal and does not affect the chart.
- If the chart is completely blank, check that you ran Cells 4 and 5 to build the df DataFrame first.
- help me debug my scatter plot
Map earthquake locations around the globe
Your histogram and scatter plot answer questions about magnitude and depth. This final chart answers a geographic question: where do earthquakes actually happen?
- Create a new cell below Cell 8 and paste this geographic scatter plot code:
plt.figure(figsize=(14, 8))
scatter = plt.scatter(
df["longitude"],
df["latitude"],
c=df["depth"],
cmap="viridis",
s=df["mag"] ** 2 * 3,
alpha=0.5,
edgecolors="none",
)
plt.colorbar(scatter, label="Depth (km)")
plt.title("Global Earthquake Locations (Past 30 Days)", fontsize=14)
plt.xlabel("Longitude", fontsize=12)
plt.ylabel("Latitude", fontsize=12)
plt.grid(alpha=0.2)
plt.tight_layout()
plt.show()
What does this geographic plot do?
- df["longitude"] and df["latitude"] plot each earthquake at its real-world geographic coordinates.
- c=df["depth"] colors each dot by depth this time (not magnitude), and cmap="viridis" uses a perceptually uniform gradient from purple (shallow) to yellow (deep).
- s=df["mag"] ** 2 * 3 sizes dots by magnitude with a smaller multiplier than Cell 8, keeping the map readable when thousands of points overlap.
- The wider figsize=(14, 8) gives the global map more horizontal space so it doesn't look squished.
Before you run this cell, take a guess. What pattern do you think earthquake locations will form on a world map?
- Run the cell by pressing Shift+Enter.
You should see a global scatter plot where earthquake dots trace out clear lines and clusters. The outlines of tectonic plate boundaries are visible from the earthquake data alone. No basemap or coastline layer needed.
Chart looks cluttered or dots are too large?
- If dots overlap heavily, make sure you used alpha=0.5 for transparency. This lets dense clusters show through layering.
- If the plot looks very different from a world map, check that you used df["longitude"] for x and df["latitude"] for y. Swapping them flips the map on its side.
- help me fix my geographic earthquake plot
✔️ Awesome, I've got everything!
Great. Double check you've saved your notebook by pressing Cmd+S (macOS) or Ctrl+S (Windows).
ⓧ I'd like to double check the full code
Your notebook should now contain nine cells in order. Cells 1 through 5 were created in earlier steps. Scroll through your notebook and confirm these four new cells are present and match the code you pasted above:
- Cell 6 - Basic unstyled histogram (plt.hist with 30 bins, no title or labels).
- Cell 7 - Styled histogram with steelblue color, black edges, title, axis labels, and grid.
- Cell 8 - Depth-vs-magnitude scatter plot with coolwarm colormap and colorbar.
- Cell 9 - Geographic scatter plot with viridis colormap, colorbar labeled "Depth (km)", and title "Global Earthquake Locations (Past 30 Days)".
You've gone from a table of raw numbers to three polished charts that tell a visual story about global earthquake activity. Next up, you'll take your analysis further with an optional Secret Mission that digs into a specific region and tracks earthquake frequency over time.
Secret mission
Regional Time-Series Analysis
Your global earthquake map reveals tectonic plate boundaries from data alone. But a data scientist also needs to zoom into a specific region and uncover trends over time. In this mission, you will filter your DataFrame to the US West Coast, count earthquakes per day, and build a time-series line chart that shows exactly when seismic activity spiked.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely on your local machine, so there are no ongoing cloud costs or paid services to worry about.
Decide whether to keep your resources running, pause them to come back later, or delete them entirely.
Resources you used:
- earthquake_analysis.ipynb Jupyter Notebook file.
- Python libraries: pandas, matplotlib, requests, and ipykernel.
- VS Code extensions: Python (ms-python.python) and Jupyter (ms-toolsai.jupyter).
Keep everything running
No action needed. Choose this if you plan to keep exploring the data or re-run the notebook with different parameters.
- Your earthquake_analysis.ipynb notebook is saved locally. You can re-run it anytime to fetch fresh earthquake data from the USGS API.
- The Python libraries and VS Code extensions stay installed and ready for your next data science project.
Pause - I'll come back to this later
Close VS Code to free up memory. Your notebook file, installed libraries, and extensions all stay in place for when you come back.
- Close VS Code.
- When you return, open earthquake_analysis.ipynb in VS Code and re-run the cells from the top. The USGS API call fetches fresh data each time.
Delete - I don't want to use this again
Remove all project files, libraries, and extensions to start fresh.
- Delete the notebook file. In your VS Code terminal, navigate to the folder where you saved earthquake_analysis.ipynb and run the appropriate command for your operating system.
macOS
rm earthquake_analysis.ipynb
Windows
del earthquake_analysis.ipynb
- Uninstall the Python libraries by running this command in your terminal:
pip uninstall pandas matplotlib requests ipykernel
You will be prompted to confirm each package removal. Type y and press Enter for each one.
- Uninstall the VS Code extensions. Press Cmd+Shift+X (macOS) or Ctrl+Shift+X (Windows) to open the Extensions view.
- Find the Python extension, click the gear icon next to it, and select Uninstall.
- Repeat for the Jupyter extension.
Nice Work!
Nice Work!
Nice work! You just built a complete data science notebook that pulls live earthquake data from a government API, wrangles it into shape, and tells a visual story with it.
You've learned how to:
- Pull live earthquake data from the USGS Earthquake Catalog API using Python's requests library, with zero authentication required.
- Transform deeply nested GeoJSON into a clean, analysis-ready pandas DataFrame with proper data types and readable columns.
- Create three styled matplotlib visualizations: a magnitude histogram, a depth-vs-magnitude scatter plot, and a geographic earthquake map.
- Secret Mission: Filtered to a geographic region and built a time-series analysis of daily earthquake frequency with an average line and peak-day annotation.
Ready to quiz yourself?