Data Analysis for Engineers/Module 1

Module 1 · Section 7 of 10

Lesson 1.6 - Working with Files

Target: ~10 min read - 20 min hands-on

Overview

Every real analysis starts with getting data into Python. This lesson reads a CSV using the built-in open() and the csv module - before Pandas (Module 2) makes this dramatically easier. We load an energy-meter log, parse it row by row, compute a summary, then write results back out.

Real logs are rarely clean - missing samples, blank cells, inconsistent timestamps. We start simple here; Module 2 goes deep on cleaning messy real-world data.

Why This Matters (PH Context)

This is the exact shape of data you'll pull from a building's energy meter, a plant utility log, or a SCADA historian export - a timestamp column and one or more value columns, thousands of rows long.

Code-Along

# Lesson 1.6 - Reading and writing files
# In the course platform, CSVs are pre-bundled and loaded via fetch();
# here we work with an in-memory example first, then show the
# open()/csv pattern you'd use with a real file.

import csv
import io

# A CSV is just text: a header row, then one comma-separated record per line.
csv_text = """timestamp,power_kW
2026-03-01T00:00,180
2026-03-01T01:00,165
2026-03-01T02:00,150
2026-03-01T03:00,300
2026-03-01T04:00,520
2026-03-01T05:00,545
"""

# io.StringIO wraps the text so it behaves like an open file object.
f = io.StringIO(csv_text)   # in real use: f = open("meter_log.csv")
# DictReader yields each row as a dict keyed by the header names.
reader = csv.DictReader(f)

rows = []
for r in reader:
    # every CSV value arrives as a STRING - convert the number with float()
    rows.append({"timestamp": r["timestamp"], "power_kW": float(r["power_kW"])})

print(f"Loaded {len(rows)} hourly readings")

# generator expressions (a list comp without the brackets) feed sum() / max()
total_kWh = sum(r["power_kW"] for r in rows)          # 1 hour per reading
peak_kW = max(r["power_kW"] for r in rows)
load_factor = (total_kWh / len(rows)) / peak_kW       # average load / peak load
print(f"Energy: {total_kWh:.1f} kWh, peak: {peak_kW:.0f} kW, load factor: {load_factor:.2f}")

# --- Writing: csv.writer + writerow() emits one comma-separated line at a time ---
out = io.StringIO()          # in real use: out = open("summary.csv", "w", newline="")
writer = csv.writer(out)
writer.writerow(["metric", "value"])          # header row
writer.writerow(["energy_kWh", total_kWh])
writer.writerow(["peak_kW", peak_kW])
writer.writerow(["load_factor", round(load_factor, 3)])

print("\nWritten CSV content:")
print(out.getvalue())        # .getvalue() reads back everything written to the buffer

Expected output:

Loaded 6 hourly readings
Energy: 1860.0 kWh, peak: 545 kW, load factor: 0.57

Written CSV content:
metric,value
energy_kWh,1860.0
peak_kW,545.0
load_factor,0.569

Practice Exercises

  1. Count how many readings are above 400 kW.
  2. Add the average power to the summary CSV.
  3. Create a second day's 6-row CSV text block, load both days, and print each day's peak.
# Try the practice exercises here

Knowledge Check

  1. Which Python module makes it easy to parse rows of a CSV file into dictionaries?
  2. Why must values read from a CSV often be explicitly converted with float()?
  3. What real-world challenge does this lesson flag as common in log data?
Answer key
  1. csv (via DictReader)
  2. All CSV values are read as strings by default
  3. Missing samples, blank cells, and inconsistent timestamps

7 / 63 sections · Course home · Join the coaching cohort