Readable implementation
Task 7 · worked step 5
The code should carry out the exact stated rules, including missing-value handling, feature order and tie-breaking. Explain these decisions rather than memorising lines.
Lab 4 PDF pp. 6–7 · Task 7
Your task
Create early-login totals and split rows. Save the training median, means, SDs and category order. Build vectors, calculate distances, choose a neighbour, then evaluate only known test outcomes.
Evidence to include
Read the code as a list of decisions.
Worked example and code
Try the task in the PDF first, then compare your working below. Run the code in your own Python notebook.
Open Lab 4 instructions (PDF)Run this after creating the df with the exact rows and columns supplied in Task 7. It follows the printed lab policy rather than choosing a new model.
import numpy as np
df['early_logins'] = df[['w1','w2','w3','w4']].sum(axis=1)
parts = {
name: df.loc[df['set'].eq(name)].copy()
for name in ['train', 'test', 'new']
}
train = parts['train']
saved_median = train['minutes'].median()
for part in parts.values():
part['minutes_imputed'] = part['minutes'].isna()
part['minutes'] = part['minutes'].fillna(saved_median)
denom = part['early_logins'].replace(0, np.nan)
part['minutes_per_login'] = part['minutes'] / denom
part['zero_logins'] = part['early_logins'].eq(0).astype(int)
numeric = ['score', 'minutes', 'early_logins']
mu = train[numeric].mean()
sd = train[numeric].std(ddof=0)
assert sd.gt(0).all()
categories = ['CS', 'Economics', 'Psychology']
def vectors(part):
z = ((part[numeric] - mu) / sd).to_numpy()
hot = np.array([
[int(p == c) for c in categories]
for p in part['programme']
])
return np.column_stack([z, hot])
train = train.sort_values('id').reset_index(drop=True)
train_vectors = vectors(train)
def predict(part):
labels = []
for row_id, v in zip(part['id'], vectors(part)):
distances = np.linalg.norm(train_vectors - v, axis=1)
# argmin picks the first minimum; IDs were sorted.
j = int(distances.argmin())
label = train.loc[j, 'outcome']
print(row_id, distances, train.loc[j, 'id'], label)
labels.append(label)
return labels
test_predictions = predict(parts['test'])
new_predictions = predict(parts['new'])
actual = parts['test']['outcome'].to_numpy()
error = np.mean(np.array(test_predictions) != actual)
print('Test error:', error, '| test n:', len(actual))
What to explain to the TA: median 90 came only from observed training minutes; scaler parameters came from completed training rows; Physics follows the saved ignore policy; outcomes were excluded from inputs; ratios involving replacements remain marked; a correct prediction on two test students is not proof of broad reliability.
Practice problems
Supplementary study questions on the lecture concepts — not verbatim exam questions. Each answer counts toward spaced review.
1. Conceptual understanding
Definitions and distinctions.
Why does the implementation sort training IDs before argmin?
Why does minutes_imputed remain useful after filling?
2. Application
Apply the concept to a case or calculation.
What does argmin return here?
Why can “is None” miss a missing numeric value in a DataFrame?
3. Interpretation and limitations
Evaluate assumptions and justify conclusions.
When should test outcomes be read for scoring?
Sorting training IDs before argmin makes what reproducible?
Explain it in writing
Self-checked, not marked. Write a few sentences, then compare with the example answer. Your writing is saved as you type.
Show an example answer
The specified rule chooses the smaller training ID. After sorting, the first minimum found by argmin follows that rule. Without a fixed rule, order could change a tied result.
Check: did you answer the question, use evidence or working, and avoid claiming more than the evidence supports?
Show an example answer
A table may store numeric missing values as NaN rather than None. The missing-value methods recognise the stored representation and handle it appropriately.
Check: did you answer the question, use evidence or working, and avoid claiming more than the evidence supports?
Saved only in this browser. This note doesn’t fill in the downloaded notebook; “reviewed” is a personal checklist, not a grade.