Chapter 8 — Programming II
Lesson map
Lesson 08 published. Map, example, EX022.
flowchart TD
N0["Learning outcomes"]
N1["8.1 Functions for measures"]
N2["8.2 Reading CSV files"]
N3["Lab — Reporting rates per branch from a CSV file"]
N4["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4
N4 --> EX["Worked example"]
EX --> Q["Exercise EX022"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["8.1 Functions for measures"]
N2["8.2 Reading CSV files"]
N3["Lab — Reporting rates per branch from a CSV file"]
N4["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> Q["EX022"]
[Learning outcomes]
|
v
[8.1 Functions for measures]
|
v
[8.2 Reading CSV files]
|
v
[Lab — Reporting rates per branch from a CSV file]
|
v
[Synthesis]
|
v
[Worked example] --> [Exercise EX022]
Learning outcomes
You will (1) write functions to compute behaviour measures; (2) read data from CSV files; (3) handle errors and document code.
8.1 Functions for measures
Nadia restructures her code into functions. One function computes the reporting rate for a branch, another the share of reports that are genuine. Functions make code reusable and testable, since each can be checked on its own. She gives them clear names and short descriptions of what they take and return. She learns that computing a rate requires guarding against division by zero, because a new branch might have no staff records yet. Small decisions like this prevent errors that could mislead managers reading the results.
8.2 Reading CSV files
Ashcombe's IT team provides a synthetic export of reports as a comma-separated values file. Nadia uses Python's csv module, which handles quoted fields and commas inside text correctly, unlike simple splitting. She reads each row into a dictionary keyed by column name, so the code remains correct even if columns are reordered. She computes reporting rates per branch and the overall share of genuine threats. The lab prints rates for each branch, and she notices that rates vary widely between similar branches.
Lab — Reporting rates per branch from a CSV file
# Reporting rates per branch from a CSV (synthetic).
import csv, io
data = "branch,staff,reports,genuine\nCentral,30,14,3\nRiverside,24,10,4\nHill,15,6,1\nMarket,14,5,1\nOakfield,10,4,2\nMill,8,3,0\nQuay,5,3,1\nElm,6,2,0\nAbbey,8,1,0\nNew,,0,0\n"
def rate(r, s): return 100 * r / s if s else None
skipped = 0; rows = []
for row in csv.DictReader(io.StringIO(data)):
if not row["staff"]: skipped += 1; continue
rows.append((row["branch"], rate(int(row["reports"]), int(row["staff"]))))
for b, r in sorted(rows, key=lambda x: -x[1]): print(f"{b}: {r:.0f} per 100 staff")
print("skipped rows:", skipped)
Run with python3 lab_csv.py. Verified output:
Quay: 60 per 100 staff
Central: 47 per 100 staff
Riverside: 42 per 100 staff
Hill: 40 per 100 staff
Oakfield: 40 per 100 staff
Mill: 38 per 100 staff
Market: 36 per 100 staff
Elm: 33 per 100 staff
Abbey: 12 per 100 staff
skipped rows: 1
8.3 Errors and documentation
Nadia adds error handling: rows with missing staff counts are logged and skipped, and the script reports how many rows it skipped so nothing is hidden. She writes a short readme explaining the input format, the measures and their limits. Documentation matters because others may reuse her script, and a measure without a definition can be misread. Dr Prescott reminds her that good code tells readers what it assumes, which is part of honest analysis as much as good engineering. She keeps it short.
Worked example
Nadia writes measure functions with zero guards, reads a CSV with the csv module and documents assumptions and skipped rows.
Synthetic case. Data are synthetic.
Errors and limits
Skipped rows may bias results. Rates for small branches are unstable.
Exercises
- EX022 — Zero guard. Why guard against division by zero? Rubric: 3 = a branch might have no staff records;; 2 = new branch;; 1 = vague;; 0 = none.
- EX023 — Highest rate. Which branch had the highest reporting rate in the lab? Rubric: 3 = Quay at 60 per hundred;; 2 = Quay;; 1 = Central;; 0 = none.
- EX024 — Skipped rows. Why report the number of skipped rows? Rubric: 3 = so nothing is hidden;; 2 = transparency;; 1 = vague;; 0 = none.
Synthesis
Functions, proper CSV reading and documented assumptions make measures trustworthy.
Continue studying — chapter 08 of 40
← Chapter 07 (draft) · Course chapter index · Chapter 09 (draft) →