DS105 2025-2026 Autumn Term Icon

💻 Week 02 Lab

Collections & API Basics - Problem-First Practice

Author

Dr Jon Cardoso-Silva

Published

15 October 2025

🥅 Learning Goals

By the end of this lab, you should be able to: i) Discover and explore unknown data structures using Python methods, ii) Navigate nested dictionaries using chained bracket notation, iii) Recognise when hardcoded approaches need loops (instructor demonstration), iv) Connect bracket notation to the DataFrames you used in Week 01.

This lab builds directly on the 📝 W02 Practice and the 🖥️ W02 Lecture. If you skipped or missed those, you might feel a bit lost. Inform your class teacher so he can instruct you on how to catch up.

📋 Preparation

  • Complete the 📝 W02 Practice (DataQuest lessons)
    • Make sure you have your notes ready and easy to access!
    • Avoid using AI chatbots to give you the answers straight away. It will only harm your learning.
  • Review the concepts from the 🖥️ W02 Lecture
  • Ensure you can access Nuvolos and launch VS Code: Using Nuvolos

🛣️ Lab Roadmap

Part Activity Type Focus Time Outcome
Part I 🗣️ TEACHING MOMENT Setup Notebook 10 min Create professional lab notebook
Part II 🔍 INVESTIGATION Explore New Data 20 min Discover structure without documentation
Part III 🗣️ TEACHING MOMENT Fix Disconnected Data 25 min Recognise when loops eliminate repetition
Part IV 🎯 ACTION POINTS Navigate Real API Data 30 min Connect to DataFrames from Week 01

👉 NOTE: Whenever you see a 🗣️ TEACHING MOMENT, this means your class teacher deserves your full attention!

Part I: Setup Your Notebook (10 min)

Note to class teachers: Welcome students and inform them that this lab has three key exercises. Don’t assume everyone has mastered the Nuvolos and VS Code interface already. It might still take a while to familiarise themselves with the interface. Keep this phase quick. You can help latecomers or those who are struggling once you have completed the first part of the lab.

Your class teacher will demonstrate how to create a notebook file from scratch and set up the first cells.

Follow along with your class teacher as they demonstrate:

  1. Open VS Code. Your teacher will show you how to access Nuvolos, locate the Applications Tab Icon Applications tab on the left and click on the VS Code application.

  2. Create a new Jupyter Notebook. Watch as your teacher right-clicks on the week02/ folder and selects “New File”. The filename will be: W02-NB02-Practice-Python-Collections.ipynb

    Try to do this at the same time as your teacher. If you fall behind, raise your hand and your class teacher will assist you.

  3. Add a professional header. Your teacher will demonstrate how to add a professional header to the notebook:

    • Make sure the first cell is a Markdown cell
    • Copy the template below into that cell
    • Customise it with today’s date and location
    • Make sure the first cell communicates the purpose of the notebook
A template you can copy and paste
# 💻 Week 02 Lab – Collections & API Basics

**LSE DS105A – Data for Data Science (2025/26)**

<div style="font-family: system-ui; padding: 20px 30px 20px 20px; background-color: #FFFFFF; border-left: 8px solid #47315E; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);max-width:600px">

**Today's Lab Session**
- 📅 [Add date here]
- ⏰ Check your class group time in your timetable
- 📍 [Add location here]

🥅 **Learning Goals**

What I've learned in this lab:

1. 
2. 
3. 

</div>
  1. Test your setup. Your teacher will add a new code cell and run this to make sure everything works:

    print("Hello from Week 02 Lab!")

    If you see the message printed below the cell, you’re ready to go!

Finished PART I early? Here’s an extra challenge for you…

Add a table of contents to your notebook using a Markdown numbered list. Create section links and add estimated completion times for each part.

Part II: Explore New Data (20 min)

Note to class teachers: You can choose to split the class as you wish. It’s fine, even encouraged, for students to work in pairs or small groups for the rest of the lab. At the end of this Part II, invoke a brief 🗣️ TEACHING MOMENT (2-3 minutes) to discuss common discoveries and the importance of exploration methods like .keys() and type(). Share solutions snippets with your class in the dedicated Slack channel in whatever format you prefer.

🎯 ACTION POINTS

  1. Add a new section in your notebook with the header ## Part II: Explore New Data, then create a code cell below it and add this mysterious data structure there:
Click here to copy the data
weather_station = {
    "station_id": "LSE_MAIN",
    "active": True,
    "location": {
        "city": "London",
        "latitude": 51.5085,
        "longitude": -0.1257
    },
    "current": {
        "temperature": 18,
        "humidity": 65,
        "conditions": "cloudy",
        "wind_speed": 12
    },
    "recent_readings": [12, 15, 14, 18, 16],
    "alerts": [],
    "last_updated": "2025-10-17T14:30:00"
}

🤔 Think about it: The variable weather_station is a dictionary. You can use the .keys() method to see what keys are in the dictionary. What else can you do with a dictionary? The W02-NB01 notebook you created as part of the 📝 W02 Practice should be a good reference for you.

  1. Discover what’s in the data

    Pretend you can’t see the code above. Write Python code to find out:

    • What is the station ID?
    • What is the city name?
    • What is the current temperature?
    • What is the first reading from recent_readings?
    • What is the last reading from recent_readings?

    Add separate code cells for each question.

💡 Remember from the 🖥️ W02 Lecture

  1. Always use type() to check what kind of data structure you’re working with.

    Try type(weather_station), then type(weather_station["location"]), then type(weather_station["recent_readings"]). This should help you know if you are working with a dictionary or a list.

  2. Once you know what you are working with, you can use the len() or the .keys() method to see what is inside.

Use your DataQuest notes to help you. Resist the temptation to use AI to get the answers straight away!

  1. Test what breaks.

    Try running these two pieces of code:

    # Test 1
    print(weather_station["city"])
    # Test 2  
    print(len(weather_station["alerts"]))
    • What happens with Test 1? Why doesn’t it work?
    • What happens with Test 2? What does it tell you about the alerts list?

    Add Markdown cell(s) with your answers.

Finished PART II early? Here’s an extra challenge for you…

This is for the advanced students.

Here’s a more complex weather monitoring system:

weather_regions = {
    "regions": {
        "london": {"temp": 18, "air_quality": "good"},
        "manchester": {"temp": 15, "air_quality": "moderate"}, 
        "birmingham": {"temp": 17, "air_quality": "good"}
    },
    "daily_readings": [12, 15, 18, 22, 19]
}

Produce a single list, extracted from the data above, that contains the three city names.

Before moving on, your class teacher will gather your thoughts on this exercise, solve any issues you might have and then they will ask you to consider the following scenario:

Why not just store the data in individual variables like this?

station_id = "LSE_MAIN"
active = True
city = "London"
temperature = 18
recent_1 = 12
recent_2 = 15
recent_3 = 14
# ... and so on

Part III: Working with Parallel Lists (25 min)

Note to class teachers: This exercise deliberately leads students to write hardcoded repetition. Let them experience it first, then use the last 5 min to check if they have spotted it as a problem and introduce them to for loops. It will be the first time that coding beginners will encounter loops. Share your loop solution in Slack afterwards.

You received some new weather data which this time is in a different format. Instead of being inside a dictionary, the data is now in three separate lists.

🎯 ACTION POINTS

  1. Create a new section ## Part III: Working with Parallel Lists and add this code:
Click here to copy the data
times = ["06:00", "07:00", "08:00", "09:00", "10:00", "11:00", "12:00", 
            "13:00", "14:00", "15:00", "16:00", "17:00", "18:00", "19:00", "20:00"]
temps = [12, 13, 15, 18, 20, 21, 22, 23, 22, 21, 19, 18, 16, 14, 13]
conditions = ["cloudy", "cloudy", "partly cloudy", "sunny", "sunny", 
                "sunny", "sunny", "sunny", "sunny", "partly cloudy", 
                "partly cloudy", "cloudy", "rainy", "rainy", "cloudy"]
  1. Print a weather report for noon. Your output should look like this:

    At 12:00, the temperature was 22°C and conditions were sunny

    The catch, though, is that you can’t just type print("At 12:00, the temperature was 22°C and conditions were sunny") into your code but instead you should collect the data from the lists and then print it out.

    💡 Refer to your DataQuest notes on string formatting and lists to help you!

  2. Create a weather table. Print all 15 observations like this:

    06:00 | 12°C | cloudy
    07:00 | 13°C | cloudy
    08:00 | 15°C | partly cloudy
    ...
    18:00 | 16°C | rainy
    19:00 | 14°C | rainy
    20:00 | 13°C | cloudy

    Create the table using separate print statements (yes, this will feel repetitive and it’s intentional for this exercise!).

  3. Test what happens when things break. Run this code:

    temps.append(12)
    print(f"Time at position 15: {times[15]}")

    What error do you get? Why did adding a temperature cause this problem?

Finished PART III early? Here’s an extra challenge for you…

You have rainfall data too:

rainfall = [2.1, 0.0, 1.5, 0.0, 0.3, 0.0, 0.8, 1.2, 3.4, 2.0, 1.1, 0.5, 4.2, 2.8, 1.0]

Create a weather report that includes rainfall: “At 12:00, the temperature was 22°C, conditions were sunny, with 0.8mm of rain”

Your class teacher will now demonstrate a better way to handle this repetitive code.

The table code you wrote is “hardcoded”. You manually wrote code for each case. You just wrote 15 print statements! Imagine if you had 100 observations, or 1000.

You’ll learn to write loops yourself in W03. For now, just observe how they eliminate repetition.

Part IV: Navigate Real API Data (30 min)

Note to class teachers: This is authentic Open-Meteo structure from the lecture. Emphasise the W01 connection: “These temperature lists will become DataFrame columns in W03!” For the final 5-7 minutes, discuss: “How does this API data connect to W01 DataFrames?” Share solutions with your class in the dedicated Slack channel in whatever format you prefer.

This is real data from the Open-Meteo weather API. Your task is to navigate this structure and extract information.

🎯 ACTION POINTS

  1. Create a new section ## Part IV: Real API Data and add this code:
Click here to copy the data
api_response = {
   "latitude": 52.52,
   "longitude": 13.419998,
   "generationtime_ms": 0.15282630920410156,
   "utc_offset_seconds": 0,
   "timezone": "GMT",
   "timezone_abbreviation": "GMT",
   "elevation": 38.0,
   "hourly_units": {"time": "iso8601", "temperature_2m": "°C"},
   "hourly": {
      "time": [
            "2025-10-09T00:00",
            "2025-10-09T01:00",
            "2025-10-09T02:00",
            "2025-10-09T03:00",
            "2025-10-09T04:00",
            "2025-10-09T05:00",
            "2025-10-09T06:00",
            "2025-10-09T07:00",
            "2025-10-09T08:00",
            "2025-10-09T09:00",
            "2025-10-09T10:00",
            "2025-10-09T11:00",
            "2025-10-09T12:00",
            "2025-10-09T13:00",
            "2025-10-09T14:00",
            "2025-10-09T15:00",
            "2025-10-09T16:00",
            "2025-10-09T17:00",
            "2025-10-09T18:00",
            "2025-10-09T19:00",
            "2025-10-09T20:00",
            "2025-10-09T21:00",
            "2025-10-09T22:00",
            "2025-10-09T23:00",
            "2025-10-10T00:00",
            "2025-10-10T01:00",
            "2025-10-10T02:00",
            "2025-10-10T03:00",
            "2025-10-10T04:00",
            "2025-10-10T05:00",
            "2025-10-10T06:00",
            "2025-10-10T07:00",
            "2025-10-10T08:00",
            "2025-10-10T09:00",
            "2025-10-10T10:00",
            "2025-10-10T11:00",
            "2025-10-10T12:00",
            "2025-10-10T13:00",
            "2025-10-10T14:00",
            "2025-10-10T15:00",
            "2025-10-10T16:00",
            "2025-10-10T17:00",
            "2025-10-10T18:00",
            "2025-10-10T19:00",
            "2025-10-10T20:00",
            "2025-10-10T21:00",
            "2025-10-10T22:00",
            "2025-10-10T23:00",
            "2025-10-11T00:00",
            "2025-10-11T01:00",
            "2025-10-11T02:00",
            "2025-10-11T03:00",
            "2025-10-11T04:00",
            "2025-10-11T05:00",
            "2025-10-11T06:00",
            "2025-10-11T07:00",
            "2025-10-11T08:00",
            "2025-10-11T09:00",
            "2025-10-11T10:00",
            "2025-10-11T11:00",
            "2025-10-11T12:00",
            "2025-10-11T13:00",
            "2025-10-11T14:00",
            "2025-10-11T15:00",
            "2025-10-11T16:00",
            "2025-10-11T17:00",
            "2025-10-11T18:00",
            "2025-10-11T19:00",
            "2025-10-11T20:00",
            "2025-10-11T21:00",
            "2025-10-11T22:00",
            "2025-10-11T23:00",
            "2025-10-12T00:00",
            "2025-10-12T01:00",
            "2025-10-12T02:00",
            "2025-10-12T03:00",
            "2025-10-12T04:00",
            "2025-10-12T05:00",
            "2025-10-12T06:00",
            "2025-10-12T07:00",
            "2025-10-12T08:00",
            "2025-10-12T09:00",
            "2025-10-12T10:00",
            "2025-10-12T11:00",
            "2025-10-12T12:00",
            "2025-10-12T13:00",
            "2025-10-12T14:00",
            "2025-10-12T15:00",
            "2025-10-12T16:00",
            "2025-10-12T17:00",
            "2025-10-12T18:00",
            "2025-10-12T19:00",
            "2025-10-12T20:00",
            "2025-10-12T21:00",
            "2025-10-12T22:00",
            "2025-10-12T23:00",
            "2025-10-13T00:00",
            "2025-10-13T01:00",
            "2025-10-13T02:00",
            "2025-10-13T03:00",
            "2025-10-13T04:00",
            "2025-10-13T05:00",
            "2025-10-13T06:00",
            "2025-10-13T07:00",
            "2025-10-13T08:00",
            "2025-10-13T09:00",
            "2025-10-13T10:00",
            "2025-10-13T11:00",
            "2025-10-13T12:00",
            "2025-10-13T13:00",
            "2025-10-13T14:00",
            "2025-10-13T15:00",
            "2025-10-13T16:00",
            "2025-10-13T17:00",
            "2025-10-13T18:00",
            "2025-10-13T19:00",
            "2025-10-13T20:00",
            "2025-10-13T21:00",
            "2025-10-13T22:00",
            "2025-10-13T23:00",
            "2025-10-14T00:00",
            "2025-10-14T01:00",
            "2025-10-14T02:00",
            "2025-10-14T03:00",
            "2025-10-14T04:00",
            "2025-10-14T05:00",
            "2025-10-14T06:00",
            "2025-10-14T07:00",
            "2025-10-14T08:00",
            "2025-10-14T09:00",
            "2025-10-14T10:00",
            "2025-10-14T11:00",
            "2025-10-14T12:00",
            "2025-10-14T13:00",
            "2025-10-14T14:00",
            "2025-10-14T15:00",
            "2025-10-14T16:00",
            "2025-10-14T17:00",
            "2025-10-14T18:00",
            "2025-10-14T19:00",
            "2025-10-14T20:00",
            "2025-10-14T21:00",
            "2025-10-14T22:00",
            "2025-10-14T23:00",
            "2025-10-15T00:00",
            "2025-10-15T01:00",
            "2025-10-15T02:00",
            "2025-10-15T03:00",
            "2025-10-15T04:00",
            "2025-10-15T05:00",
            "2025-10-15T06:00",
            "2025-10-15T07:00",
            "2025-10-15T08:00",
            "2025-10-15T09:00",
            "2025-10-15T10:00",
            "2025-10-15T11:00",
            "2025-10-15T12:00",
            "2025-10-15T13:00",
            "2025-10-15T14:00",
            "2025-10-15T15:00",
            "2025-10-15T16:00",
            "2025-10-15T17:00",
            "2025-10-15T18:00",
            "2025-10-15T19:00",
            "2025-10-15T20:00",
            "2025-10-15T21:00",
            "2025-10-15T22:00",
            "2025-10-15T23:00",
      ],
      "temperature_2m": [
            13.3,
            13.3,
            13.3,
            13.3,
            13.2,
            13.0,
            12.3,
            12.2,
            12.6,
            13.4,
            14.0,
            14.5,
            14.5,
            14.1,
            14.3,
            14.1,
            14.0,
            13.6,
            13.2,
            13.1,
            12.9,
            12.8,
            12.8,
            12.9,
            12.9,
            12.9,
            12.8,
            12.8,
            12.9,
            12.7,
            12.6,
            12.8,
            13.2,
            13.7,
            14.3,
            14.8,
            15.2,
            15.3,
            15.7,
            15.9,
            15.7,
            15.4,
            15.2,
            14.9,
            14.7,
            14.5,
            14.2,
            13.9,
            13.8,
            13.7,
            13.5,
            13.2,
            12.9,
            12.9,
            13.0,
            13.3,
            13.7,
            14.2,
            14.8,
            15.2,
            15.5,
            15.8,
            16.0,
            15.7,
            14.8,
            14.5,
            14.1,
            13.7,
            13.3,
            13.0,
            12.8,
            12.6,
            12.5,
            12.2,
            12.2,
            12.0,
            11.9,
            11.6,
            11.6,
            11.7,
            12.3,
            12.9,
            13.0,
            13.2,
            13.5,
            13.6,
            13.4,
            13.4,
            13.5,
            13.5,
            13.6,
            13.7,
            13.8,
            13.9,
            13.8,
            13.7,
            13.5,
            13.3,
            13.1,
            12.8,
            12.4,
            11.9,
            11.7,
            12.0,
            12.6,
            13.1,
            13.3,
            13.4,
            13.5,
            13.5,
            13.5,
            13.1,
            12.2,
            11.0,
            9.8,
            8.9,
            8.1,
            7.4,
            6.8,
            6.4,
            6.0,
            5.8,
            5.6,
            5.4,
            5.0,
            4.7,
            4.8,
            5.7,
            7.1,
            8.4,
            9.4,
            10.3,
            10.9,
            11.7,
            11.9,
            11.9,
            11.6,
            11.0,
            10.6,
            10.3,
            10.2,
            10.0,
            9.8,
            9.5,
            9.3,
            9.0,
            8.7,
            8.3,
            7.8,
            7.3,
            7.2,
            8.0,
            9.2,
            10.3,
            11.3,
            12.3,
            12.9,
            13.2,
            13.2,
            12.9,
            12.2,
            11.2,
            10.3,
            9.6,
            9.0,
            8.4,
            7.9,
            7.4,
      ],
   },
}
  1. Extract information from the nested structure. Write code to print:

    • The timezone
    • The complete list of times
    • The complete list of temperatures
    • Only the first 3 temperatures (remember list slicing from DataQuest?)

    🤔 Think about it: This is a dictionary that contains another dictionary inside it. How do you get to values that are nested? Your Part II work should help.

  2. Compare with Week 01. In W01, you used df['column_name'] to access DataFrame columns. What’s different about api_response["hourly"]["temperature_2m"]? What’s the same?

Finished PART IV early? Here’s an extra challenge for you…

Go to the DS105A’s Claude project, fire up a new chat and ask it to do the following:

“I’ve done the entire W02 Lab. I’m ready for a challenge!”

Your class teacher will facilitate a brief discussion about what you discovered today.

Discussion questions:

  • These temperature lists will become DataFrame columns in W03. What do you think that process will involve?