1 The Problem
We want a tool that reads a CSV file (the universal spreadsheet format) and answers real questions about it: how many rows, the average of a column, the largest value, totals per group. It teaches loading structured data and analysing it — the core of data science and analytics.
2 How to Think About It
Think about the steps from file to insight, before any code:
3 The Build — explained part by part
Here is the complete analyser. Each part is explained below.
import csv
def load_csv(filename):
# DictReader turns each row into a dictionary keyed by the header names.
with open(filename) as f:
return list(csv.DictReader(f))
def column_values(rows, column):
# Pull out one column's values, converted to numbers.
return [float(row[column]) for row in rows]
def analyse(rows, column):
values = column_values(rows, column)
return {
"count": len(values),
"total": sum(values),
"average": sum(values) / len(values),
"max": max(values),
"min": min(values),
}
if __name__ == "__main__":
rows = load_csv("data.csv")
print(f"Rows: {len(rows)}")
stats = analyse(rows, "price")
for key, value in stats.items():
print(f"{key}: {value:.2f}")
csv.DictReader(f) — the key tool: it reads the header row, then turns every following row into a dictionary keyed by those headers. So
row["price"] gives that row’s price.column_values(rows, column) — pull one column’s values out of every row, converting each to a number with
float (CSV values arrive as text).analyse(rows, column) — compute the insights using built-ins:
len (count), sum (total), sum/len (average), max and min.the for loop at the end — print each statistic neatly, formatted to two decimals.
float() — CSV values are text, so sum tries to add strings and fails.float() before computing.csv.reader instead of DictReader — then you reference columns by fragile number, not name.DictReader so you access columns by header name.4 Test & Prove Each Part
We test the analysis on a small set of known numbers, so we can check every statistic by hand.
from analyse import analyse
ROWS = [
{"price": "10"},
{"price": "20"},
{"price": "30"},
]
def test_count():
"""Three rows give a count of 3."""
assert analyse(ROWS, "price")["count"] == 3
def test_average():
"""10, 20, 30 average to 20."""
assert analyse(ROWS, "price")["average"] == 20
def test_max_and_min():
"""Max is 30, min is 10."""
stats = analyse(ROWS, "price")
assert stats["max"] == 30
assert stats["min"] == 10
Run with pytest -v. We feed analyse a tiny known dataset so every number can be verified by hand. Testing analytics against hand-checkable data is how you trust the results on real data.
5 The Interface
What it expects
name,price
Apple,1.20
Bread,2.50What it returns
Rows: 2
count: 2.00
average: 1.85
max: 2.506 Run It & Automate It
python3 analyse.pyPoint it at a
data.csv file with a numeric column and see the insights.Jenkins runs the tests automatically — each line explained below.
Rows: 100
count: 100.00
total: 4521.50
average: 45.22
max: 199.99
min: 0.99ValueError: could not convert string to float.KeyError.// Jenkinsfile — automated tests on every change.
pipeline {
agent any
stages {
stage('Get the code') { steps { checkout scm } } // download the code
stage('Install') { steps { sh 'python3 -m venv venv && . venv/bin/activate && pip install pytest' } } // test tool
stage('Test') { steps { sh '. venv/bin/activate && pytest -v' } } // run every test
}
post {
success { echo 'All tests passed.' }
failure { echo 'A test failed — look above.' }
}
}
- Group and total. Sum a column per category (sales per region). (Teaches: grouping.)
- Filter rows. Analyse only rows matching a condition. (Teaches: filtering.)
- Export a report. Write the insights to a new file. (Teaches: writing output.)
DictReader, extract a column, and compute insights with built-ins. This load-then-analyse pattern is the heart of all data work. Related: csv, Comprehensions.