Assignments

Lab 2 — Python Basics & Minimal NumPy

Due
End of Week 2
Released
Week 2
Weight
Part of 10% Attendance & Participation
CLOs
2, 5, 6

Goal

By the end of this lab you will practise the Python concepts from the Week 2 session — variables, data structures, and especially indexing & slicing — then apply three core NumPy ideas (arrays, vectorization, np.nan). Everything runs in pure Python / NumPy on list and array data (no CSV yet).

Expected effort: plan about 2–2.5 hours (in-class follow-along + take-home completion). The [Try yourself] blocks and the mini-case are longer on purpose — they combine several skills in one business scenario.

How to work: each part has [Follow along] cells (type and run with the instructor) and [Try yourself] exercises. Type by hand — do not copy-paste. Typing helps you remember.

Prepare: open a new Colab notebook or a VS Code .ipynb file. Name it lab2_YourName.ipynb (replace YourName with your full name, no spaces — e.g. lab2_NguyenVanAn.ipynb).


What to submit

Upload one notebook file to the course Google Drive folder before the end of Week 2:

Submission folder (Google Drive)

Your notebook must include:

  1. All [Follow along] cells from Parts A–D, executed successfully.
  2. Your own solutions to [Try yourself] sets B, C, and D — including every Challenge item (write them yourself — do not paste answer keys).
  3. The Integrated business mini-case (all tasks completed in your notebook).
  4. A final cell with three short answers (2–3 sentences each):
    • How is slicing different from indexing?
    • What is np.nan used for?
    • In one sentence: why does filling a missing revenue day with the mean change the “best profit day” result in the mini-case?

How to export and upload your .ipynb

From Google Colab

  1. File → Download → Download .ipynb
  2. Open the submission folder (sign in with your Google account).
  3. Click New → File upload (or drag the file into the folder).
  4. Confirm the filename is lab2_YourName.ipynb.

From VS Code

  1. Save the notebook (lab2_YourName.ipynb) on your computer.
  2. Open the same submission folder.
  3. Upload the .ipynb file as above.

Only .ipynb files are accepted. Do not submit screenshots of code or .py files unless the instructor says otherwise.


Lab overview

Part Content Time (guide)
A Start your environment 10′
B Foundations: variables, list, dict (+ challenge) 30′
C Indexing & slicing (focus) (+ challenge) 40′
D Minimal NumPy (+ missing-data challenge) 30′
E Integrated business mini-case (required) 30′
— Reflection & submit 10′

Part A — Start your environment (10′)

Choose one environment below and open a new notebook.

Option 1 — Visual Studio Code

  1. Open VS Code.
  2. File → New File → save as lab2_YourName.ipynb. VS Code opens Jupyter notebook mode.
    • If asked for a Kernel, select the Python you installed in Lab 0.
  3. Click + Code, paste the check cell below, run with ▶ or Shift + Enter.
  4. If NumPy is missing: open Terminal (Ctrl+`) and run pip install numpy (or pip3 install numpy on macOS).

Option 2 — Google Colab

  1. Go to colab.research.google.com (sign in with Google).
  2. File → New notebook.
  3. Rename the notebook to lab2_YourName (click the title at the top left).
  4. Run the check cell below. Colab already includes NumPy.

Check cell (both environments)

print("Lab 2 ready!")
import numpy as np
print("NumPy version:", np.__version__)

If you see the message and a version number → go to Part B.

Tip: in VS Code and Colab, each cell runs on its own; the last expression in a cell displays its result without print().


Part B — Foundations: variables, list, dict (30′)

B1. Variables & types — [Follow along]

price = 25000          # int
tax_rate = 0.1         # float
item_name = "Milk tea" # str
in_stock = True        # bool

print(type(price), type(tax_rate), type(item_name), type(in_stock))

Price after tax:

price_after_tax = price * (1 + tax_rate)
print(price_after_tax)   # 27500.0

B2. List — [Follow along]

revenue = [120, 150, 90, 200, 175]   # daily revenue, 5 days (million VND)
len(revenue)           # 5
revenue.append(210)    # add day 6
sum(revenue)           # total
max(revenue)           # best day

B3. Dict — [Follow along]

product = {'name': 'Latte', 'price': 45000, 'stock': 30}
product['price']              # 45000
product['discount'] = 0.15    # add a new key–value pair
print(product)

B4. None — [Follow along]

rating = None    # no rating yet
print(rating is None)   # True

Remember: empty cells in real datasets often show up as None or np.nan — we handle missing values in Weeks 3–4.

✅ [Try yourself] — Exercises B

Scenario: you manage data for a café.

Core (1–6)

  1. Create cost = [30, 45, 25, 60] (million VND, 4 months) and compute the sum and the maximum.
  2. Create customer = {'name': 'An', 'age': 28}, then add 'city' with value 'Hanoi'.
  3. Create promo_code = None (customer has not entered a code) and check whether it is None.
  4. Menu: menu = {'Latte': 45000, 'Espresso': 35000, 'Mocha': 50000}. Print the price of 'Mocha', then add 'Tea' at 30000.
  5. Today’s orders: orders = ['Latte', 'Mocha', 'Latte', 'Tea', 'Latte']. Count total cups sold, and how many 'Latte' (use .count()).
  6. Using menu from (4), compute total revenue if each item in orders is sold once (hint: add menu[item] for each item — a for loop is fine).

Challenge (7–9) — list of dictionaries

Real business data often looks like a list of records, each record a dict:

inventory = [
    {'sku': 'L01', 'name': 'Latte',    'price': 45000, 'stock': 12},
    {'sku': 'E02', 'name': 'Espresso', 'price': 35000, 'stock': 3},
    {'sku': 'M03', 'name': 'Mocha',    'price': 50000, 'stock': 0},
    {'sku': 'T04', 'name': 'Tea',      'price': 30000, 'stock': 8},
]
  1. Print the name of every item whose stock is strictly less than 5 (low stock). Collect the names in a new list low_stock.
  2. Compute the inventory value = sum of price * stock over all items. Store it in inventory_value.
  3. A delivery arrives: add 10 units to the stock of 'Espresso' (find that dict in the list and update it). Then recompute inventory_value.

Part C — Indexing & slicing (40′) — FOCUS

This is the most important skill in today’s lab. Master it and reading pandas loc / iloc in Week 4 becomes much easier.

C1. Indexing — one element — [Follow along]

Remember: indices start at 0.

drinks = ['Espresso', 'Latte', 'Cappuccino', 'Mocha', 'Americano']

drinks[0]     # 'Espresso'    — first
drinks[2]     # 'Cappuccino'
drinks[-1]    # 'Americano'   — last (negative index)
drinks[-2]    # 'Mocha'

Indexing also works on strings:

code = "SP2025"
code[0]     # 'S'
code[-1]    # '5'

C2. Slicing — a segment — [Follow along]

Syntax x[start:stop:step] — take from start up to but not including stop.

prices = [20, 35, 45, 60, 80, 95]

prices[1:4]     # [35, 45, 60]   — positions 1,2,3 (NOT 4)
prices[:3]      # [20, 35, 45]   — from start up to before 3
prices[3:]      # [60, 80, 95]   — from 3 to the end
prices[::2]     # [20, 45, 80]   — every 2nd element
prices[::-1]    # [95, 80, 60, 45, 35, 20]  — reverse

Common trap: prices[1:4] returns 3 elements, not 4 — because stop is exclusive. Watch for this.

C3. Small application — [Follow along]

week_rev = [120, 150, 90, 200, 175, 210, 160]  # Mon → Sun

# Weekday revenue (Mon–Fri)
weekdays = week_rev[:5]
print(weekdays)          # [120, 150, 90, 200, 175]

# Weekend (Sat, Sun)
weekend = week_rev[-2:]
print(weekend)           # [210, 160]

✅ [Try yourself] — Exercises C

Set 1. Given temps = [28, 30, 33, 35, 31, 29, 27] (7 days):

  1. First-day and last-day temperatures (use a negative index for the last day).
  2. First three days.
  3. From day 4 to the end.
  4. Reverse the list.
  5. Given word = "PYTHON", take the first 3 characters and the last character.

Set 2 — business scenario. Monthly revenue (billion VND):
rev = [50, 55, 48, 60, 65, 70, 72, 68, 75, 80, 90, 120]

  1. Use slicing for Q1 (first 3 months) and Q4 (last 3 months).
  2. Take the last 6 months and compute their sum.
  3. Take odd-numbered months (Jan, Mar, May, … — hint: rev[::2]).
  4. Contract code code = "VN-2025-0917". Slice the country code "VN" (first 2 chars) and the trailing number "0917" (last 4 chars).

Challenge (10–13) — combine lists + mid-string slices

months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
rev = [50, 55, 48, 60, 65, 70, 72, 68, 75, 80, 90, 120]
ticket = "INV-HN-2025-0042"
  1. Compute H1 revenue (first 6 months) and H2 revenue (last 6 months). Then compute growth = H2 total − H1 total.
  2. Find the best month name: use rev.index(max(rev)) to get the index, then look up that index in months.
  3. From ticket, extract: region code "HN" (characters after the first -, before the next -), year "2025", and serial "0042". Use slicing only (count positions carefully).
  4. Build a new list q_labels = ['Q1','Q2','Q3','Q4'] and a list q_totals with the sum of each quarter of rev (four slices). Print each label next to its total with a for loop over indices 0..3.

Part D — Minimal NumPy (30′)

NumPy is the array-computing library; pandas is built on NumPy. You only need three ideas for this course — but you will practise them on messy numbers (missing values).

D1. Arrays & indexing/slicing — [Follow along]

import numpy as np

a = np.array([10, 20, 30, 40, 50])
a[0]        # 10
a[1:3]      # array([20, 30])   — same slicing idea as list
a[-1]       # 50

2D arrays use [row, column] — a preview of a data table:

m = np.array([[1, 2, 3],
              [4, 5, 6]])
m[0, 1]     # 2              — row 0, column 1
m[:, 0]     # array([1, 4])  — all rows, column 0
m[1, :]     # array([4, 5, 6]) — row 1, all columns

D2. Vectorization — compute on the whole array — [Follow along]

revenue = np.array([120, 150, 90, 200])

revenue * 1.1     # +10% everywhere — no loop
revenue - 50      # subtract fixed cost 50 per day
revenue.mean()    # average
revenue.sum()     # total

This is why NumPy (and pandas) is fast: one operation applies to the whole array at once.

D3. np.nan — missing values — [Follow along]

b = np.array([100, 120, np.nan, 95])
print(b)                 # [100. 120.  nan  95.]
np.isnan(b)              # [False False  True False] — find missing cells

Useful helpers when data has gaps:

np.isnan(b).sum()        # how many missing
np.nanmean(b)            # mean that ignores nan

✅ [Try yourself] — Exercises D

Scenario: you analyse sales for a store chain.

Core (1–5)

  1. Create sales = np.array([200, 240, 180, 300]) (4 quarters), increase all values by 15%, then compute the mean.
  2. From the 3-store × 2-quarter table np.array([[10,20],[30,40],[50,60]]), get: store 3 / quarter 2 (row 2, column 1); and the entire column 0 (quarter 1 for every store).
  3. Create [5, np.nan, 8, np.nan] and use np.isnan() to locate missing values.
  4. On sales from (1), apply 10% VAT (* 1.1), compute the mean, then find quarters above the mean (hint: sales > sales.mean() returns a True/False array).
  5. Satisfaction scores with blanks: scores = np.array([8, np.nan, 7, 9, np.nan, 6]). Count how many missing cells (hint: np.isnan(scores).sum()).

Challenge (6–9) — clean, then analyse

import numpy as np

sales = np.array([200., 240., np.nan, 300., 180., 260.])  # 6 months, one missing
tbl = np.array([
    [10., 20., 15.],
    [30., 40., 35.],
    [50., 60., 55.],
    [25., np.nan, 40.],
])  # 4 stores × 3 quarters
  1. Count missing values in sales. Compute np.nanmean(sales).
  2. Impute: create sales_filled = sales.copy(). Replace every nan with the nan-mean from (6). Then compute the mean of sales_filled (should match the nan-mean).
  3. From tbl, extract: row 0 (store 1), column 1 (quarter 2 for all stores), and the value at store 3 / quarter 3 (tbl[2, 2]).
  4. Count missing cells in tbl. Create tbl_q1 = tbl[:, 0] (all stores, quarter 1) and compute its sum (no missing in Q1). Then create a boolean mask np.isnan(tbl) and explain in a comment which store–quarter is missing.

Integrated business mini-case (required)

Combine today’s skills in one business scenario with missing data. Complete all tasks in your notebook before submitting.

Context: you analyse a retail store for one week. Wednesday’s revenue was not recorded.

import numpy as np

days    = np.array(['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'])
revenue = np.array([120., 150., np.nan, 200., 175., 210., 160.])  # million VND
cost    = np.array([80., 95., 70., 110., 100., 120., 90.])         # million VND
store   = {
    'name': 'Store A',
    'region': 'Hanoi',
    'staff': 8,
    'open_hours': {'weekday': 10, 'weekend': 12},
}

Tasks

  1. Print store name, region, and weekday opening hours (nested dict access: store['open_hours']['weekday']).
  2. Which day name(s) have missing revenue? Hint: days[np.isnan(revenue)].
  3. Create revenue_filled = revenue.copy(). Replace missing values with np.nanmean(revenue).
  4. Compute weekday revenue (Mon–Fri) and weekend revenue (Sat–Sun) from revenue_filled using slicing; print both totals.
  5. Compute daily profit = revenue_filled - cost; store in profit.
  6. Print the average daily profit.
  7. Print the day names whose profit is strictly above the mean (days[profit > profit.mean()]).
  8. Which day has the highest profit? Use np.argmax(profit) to get the index, then index into days.
  9. Compute profit margin = profit / revenue_filled (vectorization). Compare mean weekday margin (margin[:5].mean()) vs mean weekend margin (margin[-2:].mean()). Which is higher?
  10. Business memo (4–5 sentences) in a markdown or comment cell: summarise revenue pattern, the impact of imputing Wednesday, and one recommendation for the store manager.

Wrap-up

Today you practised: variables & nested structures; indexing & slicing; NumPy arrays with missing values; and an integrated retail mini-case that forces you to clean data before deciding.

Before you leave: export lab2_YourName.ipynb and upload it to the Lab 2 Drive folder.

Worked answers (optional download): 2.Lab2_Answers.ipynb — full solution notebook with English comments. Use it to check your work after submitting.


Optional stretch (after you submit)

  1. Given months = [1,2,3,4,5,6,7,8,9,10,11,12], slice Q1, Q4, and even months.
  2. Build a 12-month revenue array with two np.nan values; impute with nanmean; plot is not required — just print before/after means.
  3. Optional reading (NEU textbook Ch. 4): sets, while loops, list comprehensions.

Troubleshooting

Problem Fix
NameError: name 'np' is not defined Run import numpy as np first
Slicing returns too few / too many items Remember: stop is exclusive
IndexError: list index out of range Index past the end; counting starts at 0
nan appears in means / comparisons Use np.nanmean / boolean masks; or impute first
VS Code missing NumPy pip install numpy (or pip3) in Terminal
Prefer no local install Use Google Colab

References