Module 23 · Extension

Work efficiently and reproducibly

Read less data, combine chunk summaries correctly, and make repeatable samples.

Before you start: Understand grouping, CSV I/O, and data types.

Python loads from this site on your first run.

Each run starts with fresh data. Download any exported files before another run. Your written answers and code drafts are saved on this device; export your work to keep a backup.

M23C01 · Explore · predict · practice

Measure memory use

memory_usage(deep=True) estimates memory including text stored by object columns. Repeated labels may use less memory as categories. The benefit depends on the data, so measure it instead of assuming.

Read the example

labels = pd.Series(["RAK", "Dubai"] * 500, dtype=object)
category = labels.astype("category")
result = pd.Series({"Object_bytes": labels.memory_usage(deep=True), "Category_bytes": category.memory_usage(deep=True)})
print(result)
Verified example output · pandas 2.2.3
Object_bytes      53132
Category_bytes     1346
dtype: int64

Watch for this. This is a small storage demonstration, not a benchmark of all pandas workloads.

Your turn

Measure 1,000 unique text labels before and after category conversion. Explain why the saving may shrink or disappear.

For the code check, keep these result variable names: category, labels. Different valid approaches are welcome.

Show a hint

Build labels such as "ID_0" through "ID_999".

Show one worked solution
labels = pd.Series([f"ID_{i}" for i in range(1000)], dtype=object)
category = labels.astype("category")
result = pd.Series({"Object_bytes": labels.memory_usage(deep=True), "Category_bytes": category.memory_usage(deep=True)})
print(result)

Categories also store the distinct labels and codes. With nearly every label unique, that overhead can outweigh any benefit.

Compare your explanations
  1. Read. It demonstrates data with few unique text values and many repeated occurrences.
  2. Predict. No. It changes their representation, not the label meanings.
  3. Explain. No. They depend on versions and storage details; compare the measurements in your environment.

One quick check

When is category often useful for memory?

What you should be able to explain. Choose data types based on meaning and measurement.

M23C02 · Explore · predict · practice

Load only needed columns

usecols avoids reading columns that the question does not need. Explicit dtypes make the import contract clearer. This small file demonstrates a habit that becomes useful with larger files.

Read the example

result = pd.read_csv(DATA_DIR / "students.csv", usecols=["Student_ID", "Program", "Score"], dtype={"Student_ID": "string", "Program": "category"})
print(result.head())
print(result.dtypes)
Verified example output · pandas 2.2.3
  Student_ID Program  Score
0       S001      AI     88
1       S002      IT     72
2       S003      AI     91
3       S004      IT     65
4       S005      IT     79
Student_ID    string[python]
Program             category
Score                  int64
dtype: object

Watch for this. A file preview can miss problems that occur later in the file.

Your turn

Read only Student_ID and Attendance, and limit the preview to the first four file rows with nrows.

For the code check, keep these result variable names: result. Different valid approaches are welcome.

Show a hint

Use nrows=4 inside read_csv.

Show one worked solution
result = pd.read_csv(DATA_DIR / "students.csv", usecols=["Student_ID", "Attendance"], nrows=4, dtype={"Student_ID": "string"})
print(result)

Only four rows and two columns are loaded. This preview does not represent the whole dataset.

Compare your explanations
  1. Read. Name, Campus, Age, Study_Hours, Attendance, and Join_Date.
  2. Predict. All 12 rows; usecols limits columns, not rows.
  3. Explain. Unneeded columns use memory and add distractions to the analysis.

One quick check

What does nrows=4 do?

What you should be able to explain. Read the fields and rows needed for the current step.

M23C03 · Explore · predict · practice

Combine chunk totals correctly

chunksize reads a CSV in pieces. A total and a non-missing count can be accumulated across pieces without keeping all rows. Divide the overall total by the overall count to calculate the overall mean.

Read the example

total = 0
count = 0
for chunk in pd.read_csv(DATA_DIR / "students.csv", usecols=["Score"], chunksize=5):
    total += chunk["Score"].sum()
    count += chunk["Score"].count()
result = total / count
print("Known scores:", count)
print("Mean score:", round(result, 2))
Verified example output · pandas 2.2.3
Known scores: 12
Mean score: 78.92

Watch for this. Not every operation is easy to compute in chunks. A global sort or median needs a different strategy.

Your turn

Use chunks of four rows and calculate how many students score at least 80 without retaining all rows.

For the code check, keep these result variable names: result. Different valid approaches are welcome.

Show a hint

Add the sum of a Boolean condition for each chunk.

Show one worked solution
result = 0
for chunk in pd.read_csv(DATA_DIR / "students.csv", usecols=["Score"], chunksize=4):
    result += chunk["Score"].ge(80).sum()
print("Students with Score >= 80:", result)

Six students meet the threshold, regardless of the chosen chunk boundaries.

Compare your explanations
  1. Read. A DataFrame containing the next group of file rows, up to five rows here.
  2. Predict. 3 chunks, with 5, 5, and 2 rows.
  3. Explain. The chunks have different counts; equal weighting would give the two-row chunk too much influence.

One quick check

What is needed for an exact combined mean?

What you should be able to explain. Combine summaries using their correct mathematical weights.

M23C04 · Explore · predict · practice

Take a repeatable sample

sample chooses rows randomly. random_state makes the selection repeatable for this data and environment. Reproducibility does not make a tiny sample representative of the population.

Read the example

df = students()
result = df.sample(n=3, random_state=7)
repeat = df.sample(n=3, random_state=7)
print(result[["Student_ID", "Campus", "Score"]])
print("Same sample:", result.equals(repeat))
Verified example output · pandas 2.2.3
   Student_ID Campus  Score
7        S008  Dubai     58
10       S011    RAK     68
2        S003    RAK     91
Same sample: True

Watch for this. Document input data, row order, library versions, and seed when an exact sample matters.

Your turn

Take two students from each campus using groupby.sample with random_state=7.

For the code check, keep these result variable names: result. Different valid approaches are welcome.

Show a hint

Group by Campus before calling sample(n=2, random_state=7).

Show one worked solution
df = students()
result = df.groupby("Campus", group_keys=False).sample(n=2, random_state=7)
print(result[["Student_ID", "Campus", "Score"]])
print(result["Campus"].value_counts())

The result has four students, two from each campus. Equal counts here are a chosen design, not a universal sampling rule.

Compare your explanations
  1. Read. Three sampled rows.
  2. Predict. Yes, within the same sampling environment.
  3. Explain. No. It makes the selection reproducible; it does not guarantee a balanced or representative sample.

One quick check

What does a seed mainly provide?

What you should be able to explain. Repeatability and representativeness are different goals.

Further detail: official documentation for this topic.