Skip to lesson content

← Python learning path

Module learning path

Python · essentials

Does zero mean the same thing as missing?

Lesson 3 of 8 · Conditions and explicit missing-value rules

A validation rule decides which observations the model is allowed to see.

Loading local progress…

Need a quick refresher?

Prerequisite recall: P01–P02. Algebra functions · Statistics. Direct entry is allowed.

The full story · about 13 minutes

Conditions and an honest answer to 'missing'

1 · Observe

Zero rupees and 'not recorded' are different

Words used in this lesson
WordWhat it means
ConditionA test that is True or False, used to choose what happens.
NonePython's value for 'nothing here' (missing).
TruthinessWhether a value counts as True in an if. 0 and None both count as False.
is NoneThe exact test for missing.
PolicyA stated rule for handling missing values.

A telecom's bill column holds 299, None, 799, 0 and 499. The 0 means the customer had a free month. The None means nobody recorded a bill. If code treats them alike, an average will be wrong and no error will tell you.

2 · Express

if, elif, else and None

if / elif / else picks the first branch that is true
x is None tests for missing
0, 0.0, '', [] and None are all falsy
Compare with None using is, not ==. Do not rely on truthiness when 0 is a valid value.

3 · Visualize

Two policies, two averages

Average bill from [299, None, 799, 0, 499]
PolicyAverage
Skip missing, keep the 0399.25
Treat missing as 0319.40

Dropping the None keeps four real values (average 399.25). Calling it 0 averages over five and understates the bill by ₹80. A truthiness filter such as [b for b in bills if b] drops the genuine 0 as well, keeping only three values.

Two policies, two averages
0100200300400Skip missing, keep the 0Treat missing as 0PolicyAverage bill (₹)
See the numbers behind this picture
Two policies, two averages
PolicyAverage
Skip missing, keep the 0399.25
Treat missing as 0319.4

4 · Discover

Say the policy out loud

There is no single right answer for missing values, only a stated one. Code should make the choice visible: an explicit `is None` check, a comment on what happens to the row, and a count of how many rows were affected.

5 · Apply

Two worked examples

Example 1, classification. describe(0) returns 'free month' and describe(None) returns 'missing', because the None check comes first.

Example 2, a range check. 18 <= age < 60 is True for 34. Python allows chained comparisons.

Check yourself

bills = [100, None, 0]. How many items does [b for b in bills if b] keep?

6 · Where it goes wrong

Three ways it goes wrong

7 · In Python

Missing values in code

Here is how to implement it, step by step. The code below does exactly these steps, and every line is editable.

  1. Write the list of bills with None for missing and 0 for a free month.
  2. Test missing with `is None`, never with plain truthiness.
  3. Keep only the observed values: [b for b in bills if b is not None].
  4. Average over the values you kept.
  5. State the policy in a comment and count how many rows were skipped.
Zero against None, and two policies
bills = [299, None, 799, 0, 499]            # None = not recorded, 0 = recorded as zero rupees

def describe(b):
    if b is None:
        return "missing"
    elif b == 0:
        return "free month"
    elif b < 500:
        return "low"
    else:
        return "high"
print([describe(b) for b in bills])

# the truthiness trap: 0 and None are both falsy
print("keep only truthy values:", [b for b in bills if b])
print("keep only observed values:", [b for b in bills if b is not None])
observed = [b for b in bills if b is not None]
print("average bill treating missing as skipped:", sum(observed) / len(observed))
print("average bill treating missing as 0:", sum(b or 0 for b in bills) / len(bills))

# chained conditions and booleans
age = 34
print("18 <= age < 60:", 18 <= age < 60, "| not (age > 40):", not (age > 40))
['low', 'missing', 'high', 'free month', 'low']
keep only truthy values: [299, 799, 499]
keep only observed values: [299, 799, 0, 499]
average bill treating missing as skipped: 399.25
average bill treating missing as 0: 319.4
18 <= age < 60: True | not (age > 40): True
Edit and run this code in your browser

Live Python

Zero against None, and two policies

Runs in your browser on your device. Nothing you type is sent anywhere, and nothing here changes your saved progress.

Press Ctrl+Enter (⌘+Enter on Mac) to run. Tab moves focus to the next control, as usual; use spaces to indent.

Explore one controlled change

Experiment: trace one meaningful change

Pick a version of the program, predict exactly what it prints, then reveal the real output and say why. Change the configuration at least once to complete the activity.

records = [('A3', 0), ('B3', None), ('C3', 3)]
kept = [row_id for row_id, age in records if age is not None]
print(kept)
What will this program print?

Activity not yet demonstrated.

Why this matters

A validation rule decides which observations the model is allowed to see.

Mathematical intuition: Domains, Boolean predicates and threshold decisions.

Terminology: comparison, if/elif/else, and/or/not, None, truthiness.

Worked starting point: age=0 is valid but age=None is missing. if age is None: flag_missing=True must not be replaced by if not age.

Now change the conditions: Contrast valid age zero, missing age and a boundary threshold.

Common misconception: Zero, False and missing do not mean the same thing; = is not ==.

Essentials teaching and guided practice

Evaluate comparisons and compound Boolean conditions.

Evaluate both comparisons at the boundary; >= includes equality while < excludes its upper endpoint.

Worked example

age = 3
print(age >= 3 and age < 5)
True
Edit and run this code in your browser

Live Python

P03.O1 worked

Runs in your browser on your device. Nothing you type is sent anywhere, and nothing here changes your saved progress.

Press Ctrl+Enter (⌘+Enter on Mac) to run. Tab moves focus to the next control, as usual; use spaces to indent.

Not this: False is a tempting but wrong answer. Build its truth table one condition at a time.

Success means: Predict a new bounded eligibility/validation predicate.

Evaluate comparisons and compound Boolean conditions.

Not passed yet. Version A · 0 of 2 correct answers in a row.

Predict a new bounded eligibility/validation predicate. Predict the result or error of this supplied program; preserve types, order and row identity.

age = 1
print(age >= 1 and age < 3)
Result / reasoning outcome

Distinguish a legitimate zero from None in a data rule.

Zero is a legitimate observed value. Test is not None, rather than truthiness, so the zero-valued record is not silently lost.

Worked example

records = [('A3', 0), ('B3', None), ('C3', 3)]
kept = [row_id for row_id, age in records if age is not None]
print(kept)
['A3', 'C3']
Edit and run this code in your browser

Live Python

P03.O2 worked

Runs in your browser on your device. Nothing you type is sent anywhere, and nothing here changes your saved progress.

Press Ctrl+Enter (⌘+Enter on Mac) to run. Tab moves focus to the next control, as usual; use spaces to indent.

Not this: C3 is a tempting but wrong answer. Compare records with 0, None and an ordinary positive value.

Success means: Repair a missingness branch and justify why zero is retained.

Distinguish a legitimate zero from None in a data rule. — a key decision: choose, then explain

Not passed yet. Version A · 0 of 2 correct answers in a row.

Repair a missingness branch and justify why zero is retained. Predict the result or error of this supplied program; preserve types, order and row identity.

records = [('A1', 0), ('B1', None), ('C1', 1)]
kept = [row_id for row_id, age in records if age is not None]
print(kept)
Result / repair outcome
Explain why that outcome is justified

Trace mutually exclusive if/elif/else branches.

An if/elif chain executes the first satisfied branch; test the exact boundary before choosing a later branch.

Worked example

age = 3
if age < 3:
    branch = 'low'
elif age <= 4:
    branch = 'middle'
else:
    branch = 'high'
print(branch)
middle
Edit and run this code in your browser

Live Python

P03.O3 worked

Runs in your browser on your device. Nothing you type is sent anywhere, and nothing here changes your saved progress.

Press Ctrl+Enter (⌘+Enter on Mac) to run. Tab moves focus to the next control, as usual; use spaces to indent.

Not this: high is a tempting but wrong answer. Annotate the first satisfied branch.

Success means: Choose which output is reached at boundary values.

Trace mutually exclusive if/elif/else branches.

Not passed yet. Version A · 0 of 2 correct answers in a row.

Choose which output is reached at boundary values. Predict the result or error of this supplied program; preserve types, order and row identity.

age = 1
if age < 1:
    branch = 'low'
elif age <= 2:
    branch = 'middle'
else:
    branch = 'high'
print(branch)
Result / reasoning outcome

Reject a condition that changes the intended population.

This truthiness filter accidentally drops valid zero A as well as missing C. A plausible row count does not prove the intended population was kept.

Worked example

records = [('A', 0), ('B', 3), ('C', None)]
kept = [row_id for row_id, age in records if age]
print(kept)
['B']
Edit and run this code in your browser

Live Python

P03.O4 worked

Runs in your browser on your device. Nothing you type is sent anywhere, and nothing here changes your saved progress.

Press Ctrl+Enter (⌘+Enter on Mac) to run. Tab moves focus to the next control, as usual; use spaces to indent.

Not this: ["A","B"] is a tempting but wrong answer. Compare the retained row IDs, not just the count.

Success means: Identify an accidentally dropped valid record.

Reject a condition that changes the intended population.

Not passed yet. Version A · 0 of 2 correct answers in a row.

Identify an accidentally dropped valid record. Predict the result or error of this supplied program; preserve types, order and row identity.

records = [('A', 0), ('B', 1), ('C', None)]
kept = [row_id for row_id, age in records if age]
print(kept)
Result / reasoning outcome

Scoped lesson reset

Independent assessment · Essentials notebook. Neither lesson completion nor notebook use awards mastery.

Make the idea yours

How could a truthiness check accidentally discard a valid observation? State an explicit missing-value rule instead.

Explain the mechanism and give a small example. A matching output alone does not establish why it happened.

Check your explanation against the key distinction

Zero, False and missing do not mean the same thing; = is not ==.

Unscored reflection; it does not add to your assessment record.
Read a larger ML expression
Equation X-Ray · Read the structure, then explain it

Mathematics as a language

One rule, many possibilities

A trip has a 3-rupee booking fee and costs 2 rupees per kilometre. How can one statement describe any permitted distance?

y = 2x + 3

Read the relationship before trying to solve it. This is an illustrative example, separate from the live experiment.

Choose a building block to inspect its role.

Read the operations: Multiply distance by its rate, then add the fee. If a bill is known, solving asks which distance makes both sides equal.

Build the expression from smaller operations

Choose a valid construction in the stated order. This exercise organizes dependencies; it does not claim every implementation must evaluate independent branches in this order.

    What problem could this relationship represent?

    A booking fee plus a distance charge is one possible interpretation; a fixed production setup cost plus a per-item charge has the same structure.

    Context we still need: Symbols alone do not establish currency, physical meaning or whether negative distances are allowed.

    Connect the operations to code
    bill = 2 * distance_km + 3

    Read the code as a map of operations. It is not executed here; imports, shapes and numerical safeguards depend on the actual lesson.

    Explain a changed situation

    Review the five-level equation-reading journey →

    Your notes and reveals are temporary. This reading practice does not change lesson completion or saved assessment evidence.

    Carry the idea forward

    Before continuing, explain what changed, why the code produced that result, and which assumptions mattered.