💻 Week 02, Day 04 - Lab
Nested JSON with PokéAPI
By the end of this lab, you should be able to: i) Run named functions that collect JSON and images, and notice how nice it is to know what a function does from its name, ii) Build one row of key fields for a Pokémon, wrap that step in a function, and join several Pokémon with pd.concat, iii) Flatten nested stats with pd.json_normalize the same way across the batch, iv) Move those functions into utils.py and import them after a kernel restart.
⏰ Thursday, 23 July 2026 | Check your timetable for your class time 📍 Check your timetable for the location of your class
This afternoon let’s practice writing functions and using pd.json_normalize to reshape JSON from a new API: PokéAPI (no API key needed).
🛣️ Lab Roadmap
| Part | Time | What you do |
|---|---|---|
| Part I | ~25 min | Collect JSON and images |
| Part II | ~25 min | One row of key fields, a function, then join the batch into a CSV |
| Part III | ~25 min | Flatten stats the same way across the batch |
| Part IV | Remaining | Move functions into utils.py, restart, import |
Before you start
Open the starter notebook ME204_W02D04_Lab.ipynb in VS Code on Nuvolos (or your local copy of the course materials).
Work with the notebook folder as your working directory so data/ is created next to the notebook, then run the imports cell at the top before Part I.
Part I: Collect JSON and images
Collect one JSON file and one image per name in the batch under data/.
🎯 Action points
Run
collect_pokemon("pikachu"), then the loop overPOKEMON_BATCH, and confirm you get one.jsonfile per name underdata/.Run
download_pokemon_imagesthe same way. You do not need to study the body of that function. Even if you skip reading the code inside it, that is a good name, isn’t it? Just notice how nice it is to know what a function does just by reading its name!List the PNGs under
data/images/, display Pikachu, then opendata/pikachu.jsonin the editor and scroll it as plain text before you reshape anything.
Part II: One row of key fields, then many
Start from the pokemon dict for Pikachu and end with data/pokemon_rows.csv (one row per Pokémon in the batch).
Try each step yourself first. Your class teacher will show or share a solution when the room is ready.
🎯 Action points
Build
pokemon_rowfor Pikachu withid,name,height,weight, andbase_experience. Match the preview table in the notebook.Write
pokemon_row_from_file(path)so one saved JSON file becomes that same table with a single row.Build
pokemon_rowsfor the whole batch (one row per Pokémon), match the preview in the notebook, and writedata/pokemon_rows.csv.
Part III: Stats for one Pokémon, then many
Flatten pokemon["stats"] with this morning’s pd.json_normalize pattern, then do the same for the whole batch.
Try each step yourself first. Your class teacher will show or share a solution when the room is ready.
🎯 Action points
Turn
pokemon["stats"]into a DataFrame namedstatsthat matches the preview in the notebook.Write
stats_from_file(path)that does the same for one saved JSON file.Build
stats_allfor every Pokémon in the batch. Optional: meanbase_statby Pokémon name with.groupby.
Part IV: A small utils.py
Move collect_pokemon, pokemon_row_from_file, stats_from_file, and download_pokemon_images into utils.py next to the notebook, restart the kernel, and import them.
🎯 Action points
Create
utils.pyin the same folder as the notebook (not insidedata/).Move into it:
collect_pokemon,pokemon_row_from_file,stats_from_file, anddownload_pokemon_images, plus the imports and constants they need (DATA_DIR,IMAGES_DIR,BASE_URL).Save, then choose Kernel → Restart Kernel and Clear Outputs of All Cells.
Run a fresh cell that imports from
utilsand call one function to prove it worked. Your cell should look like this:
from utils import (
DATA_DIR,
IMAGES_DIR,
collect_pokemon,
download_pokemon_images,
pokemon_row_from_file,
stats_from_file,
)
collect_pokemon("pikachu")New tool: importing from a neighbouring .py file. from utils import collect_pokemon means “open utils.py and bring that name into this notebook.” Without a restart, Python may keep using the old function objects from earlier cells even after those cells are gone.
Closing
Before you leave: JSON under data/, images under data/images/, pokemon_rows.csv, a joined stats table in the notebook, and a working import from utils.py.
If the import step fails, ask your class teacher before you leave. The usual causes are utils.py in the wrong folder, a missing save, or skipping the kernel restart.