Python for Humans · Draft v0.1 · Oct 29, 2026 · Draft position: chapter 22 · First short project draft.

Explore Real Data

You should already know
CSV files, missing values and saved public data from The Web.
You'll build
An annotated notebook with a count, a ranked table and a histogram.
You'll be able to
Run notebook cells, filter a dataframe, inspect missing data and label a chart.
You need
Your local setup, any plain-text editor, uv and internet access for installing packages. Python 3.14 is selected for these examples.

A script is useful when you know the report you want. A notebook gives you a place to try a question, inspect a small result and write down what it means.

We'll use JupyterLab to open a notebook, pandas to work with a table and Matplotlib to draw a chart. The source is a saved USGS feed, so repeating the analysis doesn't silently fetch a different day's data.

Open the Notebook

mkdir earthquake-notebook
cd earthquake-notebook
uv init --bare --vcs none --no-workspace --python 3.14
uv python pin 3.14
uv add jupyterlab pandas matplotlib

Save these files in this new folder:

Run uv run jupyter lab. The command normally opens a browser; if it doesn't, use the local URL printed in the terminal. Open earthquakes.ipynb in JupyterLab. Use the Python 3 kernel from this project.

A notebook has code cells and Markdown cells. Select a cell and press Shift-Enter to run it and move on. Markdown cells hold your explanations. The kernel is the Python process remembering variables between code cells.

Read each cell and predict its small result before running it. Use Kernel → Restart Kernel and Run All Cells at the end to check that the notebook works in order from a fresh state. Stop JupyterLab with Ctrl-C in its terminal when finished.

Inspect Before Counting

The first cell reads the local CSV:

import pandas as pd
import matplotlib.pyplot as plt

raw = pd.read_csv('earthquakes.csv')
raw.head()

pd is the conventional short import name for pandas. The result is a DataFrame, a table with named columns. .head() displays its first few rows. A selected column such as raw['mag'] is a Series.

The notebook prints the event types and selects earthquake rows:

quakes = raw.loc[raw['type'] == 'earthquake'].copy()
quakes['mag'] = pd.to_numeric(quakes['mag'], errors='coerce')
print('Missing magnitudes:', quakes['mag'].isna().sum())

The comparison produces a Boolean value for each row; .loc[...] uses that selection. .copy() gives us a table we can change separately. Numeric conversion uses missing values for entries that can't be converted, rather than guessing zero.

The notebook drops missing magnitudes only for calculations that require them. Its missing-value count remains visible. Compare the magnitude-at-least-2.5 result with your chapter 15 analyzer on this same CSV.

Draw and Question a Chart

The histogram groups reported magnitudes into intervals:

known = quakes.dropna(subset=['mag'])
fig, ax = plt.subplots(figsize=(7, 4))
ax.hist(known['mag'], bins=15, edgecolor='white')
ax.set(xlabel='Reported magnitude', ylabel='Earthquake records',
       title='Magnitudes in one saved USGS feed')
fig.tight_layout()
plt.show()

fig is the whole figure; ax is the plotting area. bins controls the number of magnitude intervals. Each bar's height counts records in its interval. The labels state what was measured, rather than leaving the reader to infer the units and source.

This dated past-day feed isn't a complete census of worldwide earthquakes. Read the USGS field documentation, including magnitude methods and revisions, before interpreting a pattern scientifically.

Your Turn

Change the threshold to 3.0, recording your prediction in a Markdown cell first. Compare the result with 2.5. Changing a rule shouldn't alter the saved input.

Try 5 and 30 histogram bins. Explain which apparent patterns change with that choice. Then restart the kernel and run everything in order. A result depending on a deleted or out-of-order cell is a notebook bug.

An alternative dataset is an invented bank export: categorize transactions and plot spending by category. Use a reproducible sample before substituting personal data. You can also export a chart with fig.savefig('magnitudes.png') and include its source and retrieval date in a short report.

What I've Learned

Explain how a notebook's saved code, displayed output and running kernel can disagree, and how Restart and Run All helps check your work.

The next two projects use notebooks to train classifiers. You can keep exploring data without taking that next step.