Skip to content

Beginner: data foundations · Python for data · topic 5 of 62 · 30 min

Writing data code that others can trust

Explanation

Data results are only useful if people can trust and repeat them. Put each step in a small function with a clear name, check it with asserts on normal and edge cases, keep the raw data unchanged, fix random seeds, and record the libraries you used in a virtual environment.

Why trust matters

A wrong number in a report can cost money or hurt people: a bank may approve bad loans, a hospital may order too few medicines. Data code also tends to fail silently. It does not crash; it just gives a slightly wrong answer, and nobody notices. So data people build habits that make mistakes visible early and make results repeatable. Reproducible means that someone else, or you next month, can run the same code on the same data and get the same answer.

Small functions with clear names

Put each step in its own function that does one job, such as clean_price, total_per_city or safe_mean. A function can be tested on its own and reused on next month's file. A clear name says what comes out: average_bill_rupees is better than x2 or temp. Add a one-line docstring that says what goes in, what comes out, and what happens with odd input.

Edge cases

An edge case is an unusual input at the boundary: an empty list, a single value, a blank cell, a negative number, a tie. Most bugs live there. Before writing a function, list the edge cases and decide what should happen. For example, the average of an empty list has no sensible number, so returning None (and saying so in the docstring) is safer than crashing or quietly returning 0.

python
def safe_mean(values):
    """Average of the numbers in values, ignoring None. Returns None if there are no numbers."""
    numbers = [v for v in values if v is not None]
    if not numbers:
        return None
    return sum(numbers) / len(numbers)

print(safe_mean([10, 20, None, 30]))   # 20.0
print(safe_mean([]))                   # None
Missing values are skipped, and an empty input gives None instead of a ZeroDivisionError.

Asserts as tiny tests

assert checks that something is true. If it is false, the program stops with an AssertionError and your message. A few assert lines under a function act as tests: they prove it works on normal cases and edge cases, and they fail loudly if a later change breaks it. This is exactly how the tasks in this course are checked.

python
assert safe_mean([10, 20, 30]) == 20, "normal case"
assert safe_mean([]) is None, "empty list gives None"
assert safe_mean([None, None]) is None, "only missing values gives None"
assert safe_mean([5]) == 5, "one value is its own mean"
print("all tests passed")   # all tests passed
When every assert passes, nothing is printed except your own message. Bigger projects use the pytest tool, which runs files full of tests like these.

Notebooks and scripts

A notebook (Jupyter, or Google Colab in the browser) is great for exploring: you run small cells and see tables and charts at once. Its danger is hidden state: cells can be run out of order, so the notebook on screen may not match what a fresh run gives. A script is a plain .py file that runs from top to bottom every time, which suits jobs that run daily. A good habit: explore in a notebook, then move the finished steps into functions in a .py file, and before sharing a notebook use "Restart and run all" to prove it works from the top.

Virtual environments and pip

Libraries such as pandas are installed with pip, Python's package installer. Different projects may need different versions, so each project gets its own virtual environment: a private folder of installed packages. requirements.txt records the exact versions so others can rebuild the same setup.

bash
python -m venv .venv
# Windows:      .venv\Scripts\activate
# macOS/Linux:  source .venv/bin/activate
pip install pandas
pip freeze > requirements.txt
# Later, on another computer:
pip install -r requirements.txt
Shown only. Colab already has pandas, NumPy and scikit-learn installed.

Reproducibility habits

  • Never edit the raw data file. Keep it read-only and write cleaned data to a new file, so you can always start again.
  • Do every cleaning step in code, not by hand in Excel, so the steps are recorded and can be re-run.
  • Fix the random seed whenever randomness is used (sampling, shuffling, splitting data for machine learning), so the result is the same every run.
  • Write down where the data came from and on what date, because sources change.
python
import random

random.seed(42)
first = random.sample(range(1, 101), 3)
random.seed(42)
second = random.sample(range(1, 101), 3)
print(first == second)   # True
With the same seed, the "random" sample is identical every time. scikit-learn uses random_state=42 for the same purpose.

Common mistakes

  • Testing only the happy case. Fix: always add asserts for empty input, one item, blanks and ties.
  • Overwriting the raw file with cleaned data. Fix: save to a new file such as sales_clean.csv.
  • Sharing a notebook that only works when cells run in a special order. Fix: Restart and run all before sharing.
  • Installing everything into the main Python. Fix: one virtual environment per project, plus requirements.txt.
  • Returning 0 when a value is missing. Fix: return None and document it, so missing is never mistaken for zero.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Writing data code that others can trust · 1/7

Code others can trust

In this lesson you will learn the habits that make data code trustworthy and repeatable.

Prefer a video by a teacher? Find free videos on “reproducible data analysis python virtual environment jupyter best practices” on YouTube ↗

In real life: A monthly report at a hospital

A hospital analyst prepares a monthly report of average waiting time per department. The raw export from the hospital system is kept untouched. A script reads it, cleans times with tested functions, skips missing values, and writes a cleaned file and a summary table. Because the script and requirements.txt are saved, a colleague can re-run last month's report and get exactly the same numbers when an auditor asks.

python
def clean_minutes(text):
    """'45 min' -> 45; blank or invalid -> None."""
    text = text.replace("min", "").strip()
    return int(text) if text.isdigit() else None

assert clean_minutes("45 min") == 45
assert clean_minutes("") is None
assert clean_minutes("n/a") is None
print([clean_minutes(t) for t in ["30 min", "", "55min"]])
Output: [30, None, 55].

Practice (0/3 done)

Task 1 · Code · Python

Write safe_mean(values) that returns the average of the numbers in values, rounded to 2 decimal places, ignoring any None items. If there are no numbers (empty list, or only None), return None.

Task 2 · Code · Python

Prices come from a form as text, like "₹1,250", " 99.5 " or "". Write clean_price(text) that removes spaces, the ₹ sign and commas, and returns the price as a float. If the result is empty or not a number, return None.

Task 3 · Practice

A classmate shares a Jupyter notebook that calculates the average monthly electricity bill of 200 homes from bills.csv. Write a short review checklist you would use before trusting the result, and say what you would ask them to change.

Quick quiz

Question 1

1.What does "reproducible" mean for a data analysis?

Question 2

2.Why should the average of an empty list return None rather than 0?

Question 3

3.What is the main risk of a Jupyter notebook?

Question 4

4.What does random.seed(42) do?

Question 5

5.What is requirements.txt for?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What does "reproducible" mean for a data analysis?

Answer: Someone else can run the same code on the same data and get the same result

Reproducible results can be checked and repeated, which is the base of trust.

Why should the average of an empty list return None rather than 0?

Answer: 0 is a real value and could be mistaken for a true average of zero

Returning None makes "no data" visible, while 0 would quietly look like a real answer.

What is the main risk of a Jupyter notebook?

Answer: Cells can be run out of order, so the results may not match a fresh run

This hidden state is why you restart and run all before sharing.

What does random.seed(42) do?

Answer: Makes the following random numbers the same on every run

A fixed seed makes "random" results repeatable, which is essential for reproducible work.

What is requirements.txt for?

Answer: Recording the library versions so others can install the same setup

pip freeze writes the installed versions; pip install -r requirements.txt rebuilds them.

Why use a virtual environment?Related

Answer: To give each project its own packages and versions

Each project gets a private set of packages, so version clashes between projects do not happen.

From Virtual environments and pip

Which of these is an edge case for a discount function?Related

Answer: A cart total of 0 rupees

Edge cases sit at the limits: empty, zero, negative, very large. Zero is a classic one.

From Unit testing: checking one piece at a time

Which is an edge case for a function that checks if marks pass (pass mark 35)?Related

Answer: Marks of exactly 35

Exactly at the limit is the border, where off-by-one mistakes (> instead of >=) show up.

From Testing your code

Your function returns None and the caller does result[0]. Which error appears?Related

Answer: TypeError: 'NoneType' object is not subscriptable

Indexing None is a TypeError; it usually means a missing return statement.

From Testing, edge cases and debugging under pressure

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. This is the last topic of “Python for data”. The module exam comes next.
  2. Module 1 exam: Python for data · 14 questions · 20 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Statistics made simple. 62 topics left in the course before the final exam.

← Previous: Counting and grouping: collections and statistics