Lab 2 — Python Basics & Minimal NumPy
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:
- All [Follow along] cells from Parts A–D, executed successfully.
- Your own solutions to [Try yourself] sets B, C, and D — including every Challenge item (write them yourself — do not paste answer keys).
- The Integrated business mini-case (all tasks completed in your notebook).
- A final cell with three short answers (2–3 sentences each):
- How is slicing different from indexing?
- What is
np.nanused 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
- File → Download → Download .ipynb
- Open the submission folder (sign in with your Google account).
- Click New → File upload (or drag the file into the folder).
- Confirm the filename is
lab2_YourName.ipynb.
From VS Code
- Save the notebook (
lab2_YourName.ipynb) on your computer. - Open the same submission folder.
- Upload the
.ipynbfile as above.
Only
.ipynbfiles are accepted. Do not submit screenshots of code or.pyfiles 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
- Open VS Code.
- 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.
- Click + Code, paste the check cell below, run with ▶ or
Shift + Enter. - If NumPy is missing: open Terminal (
Ctrl+`) and runpip install numpy(orpip3 install numpyon macOS).
Option 2 — Google Colab
- Go to colab.research.google.com (sign in with Google).
- File → New notebook.
- Rename the notebook to
lab2_YourName(click the title at the top left). - 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
Noneornp.nan— we handle missing values in Weeks 3–4.
✅ [Try yourself] — Exercises B
Scenario: you manage data for a café.
Core (1–6)
- Create
cost = [30, 45, 25, 60](million VND, 4 months) and compute the sum and the maximum. - Create
customer = {'name': 'An', 'age': 28}, then add'city'with value'Hanoi'. - Create
promo_code = None(customer has not entered a code) and check whether it isNone. - Menu:
menu = {'Latte': 45000, 'Espresso': 35000, 'Mocha': 50000}. Print the price of'Mocha', then add'Tea'at30000. - Today’s orders:
orders = ['Latte', 'Mocha', 'Latte', 'Tea', 'Latte']. Count total cups sold, and how many'Latte'(use.count()). - Using
menufrom (4), compute total revenue if each item inordersis sold once (hint: addmenu[item]for each item — aforloop 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},
]
- Print the name of every item whose
stockis strictly less than 5 (low stock). Collect the names in a new listlow_stock. - Compute the inventory value = sum of
price * stockover all items. Store it ininventory_value. - A delivery arrives: add 10 units to the stock of
'Espresso'(find that dict in the list and update it). Then recomputeinventory_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 — becausestopis 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):
- First-day and last-day temperatures (use a negative index for the last day).
- First three days.
- From day 4 to the end.
- Reverse the list.
- 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]
- Use slicing for Q1 (first 3 months) and Q4 (last 3 months).
- Take the last 6 months and compute their sum.
- Take odd-numbered months (Jan, Mar, May, … — hint:
rev[::2]). - 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"
- Compute H1 revenue (first 6 months) and H2 revenue (last 6 months). Then compute growth = H2 total − H1 total.
- Find the best month name: use
rev.index(max(rev))to get the index, then look up that index inmonths. - From
ticket, extract: region code"HN"(characters after the first-, before the next-), year"2025", and serial"0042". Use slicing only (count positions carefully). - Build a new list
q_labels = ['Q1','Q2','Q3','Q4']and a listq_totalswith the sum of each quarter ofrev(four slices). Print each label next to its total with aforloop over indices0..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)
- Create
sales = np.array([200, 240, 180, 300])(4 quarters), increase all values by 15%, then compute the mean. - 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). - Create
[5, np.nan, 8, np.nan]and usenp.isnan()to locate missing values. - On
salesfrom (1), apply 10% VAT (* 1.1), compute the mean, then find quarters above the mean (hint:sales > sales.mean()returns a True/False array). - 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
- Count missing values in
sales. Computenp.nanmean(sales). - Impute: create
sales_filled = sales.copy(). Replace everynanwith the nan-mean from (6). Then compute the mean ofsales_filled(should match the nan-mean). - 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]). - Count missing cells in
tbl. Createtbl_q1 = tbl[:, 0](all stores, quarter 1) and compute its sum (no missing in Q1). Then create a boolean masknp.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
- Print store name, region, and weekday opening hours (nested dict access:
store['open_hours']['weekday']). - Which day name(s) have missing revenue? Hint:
days[np.isnan(revenue)]. - Create
revenue_filled = revenue.copy(). Replace missing values withnp.nanmean(revenue). - Compute weekday revenue (Mon–Fri) and weekend revenue (Sat–Sun) from
revenue_filledusing slicing; print both totals. - Compute daily profit =
revenue_filled - cost; store inprofit. - Print the average daily profit.
- Print the day names whose profit is strictly above the mean (
days[profit > profit.mean()]). - Which day has the highest profit? Use
np.argmax(profit)to get the index, then index intodays. - Compute profit margin =
profit / revenue_filled(vectorization). Compare mean weekday margin (margin[:5].mean()) vs mean weekend margin (margin[-2:].mean()). Which is higher? - 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)
- Given
months = [1,2,3,4,5,6,7,8,9,10,11,12], slice Q1, Q4, and even months. - Build a 12-month revenue array with two
np.nanvalues; impute withnanmean; plot is not required — just print before/after means. - Optional reading (NEU textbook Ch. 4): sets,
whileloops, 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
- Week 2 slides:
2.Basic_Py.pdf(Materials on the course site) - NEU. Data Science for Economics and Business (Python) — Chapter 4: Python basics
- Continues into pandas in Week 4 (
loc/ilocbuild on today’s slicing)