Beginner: data foundations · Python for data · topic 5 of 62 · 30 min
Writing data code that others can trust
Explanation
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.
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([])) # NoneAsserts 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.
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 passedNotebooks 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.
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.txtReproducibility 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.
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) # TrueCommon 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
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.
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"]])Practice (0/3 done)
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.
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.
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
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Reading CSV and JSON with the standard libraryPython for data · same module
- Python essentials for data: records, lists and dictionariesPython for data · same module
- Virtual environments and pipPython Programming · Python in the real world
- Unit testing: checking one piece at a timeBackend Development · Testing and API documentation
- Testing your codePython Programming · Algorithms, data structures and testing
- Testing, edge cases and debugging under pressureData Structures and Algorithms (DSA) for interviews · Interview strategy and mock problems
Questions people ask about this
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.
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.
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.
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
- This is the last topic of “Python for data”. The module exam comes next.
- Module 1 exam: Python for data · 14 questions · 20 min, without help. 5 topics of this module still to finish first.
- Then the next module, Statistics made simple. 62 topics left in the course before the final exam.
← Previous: Counting and grouping: collections and statistics