Understanding nested loops in Python
Think about an analog clock such as the one below.
Figure 1. An analog clock.
Image: Wikimedia Commons.
For every complete rotation of the second hand, the minute hand advances by one minute. Same goes for the hour hand; for every complete rotation of the minute hand, the hour hand advances by one hour.
Programming sometimes requires this same kind of repetition. But how can we tell Python to repeat one task inside another repeated task?
The answer lies in nestedloops. By definition, a nested loop is simply a loop placed inside another loop.
For every iteration of the outer loop, the inner loop runs from beginning to end before the outer loop moves to its next iteration.
Much like the hour and minute hands on an analog clock, the outer loop advances one step only after the inner loop has completed all of its iterations.
In data analysis, nested loops are particularly useful when you need to work through two levels of data, such as rows and columns in a dataset, households within counties, or regions and their characteristics.
A nested loop can be made from any combination of for and while loops. However, you'll most commonly use a for loop inside another for loop.
Syntax
for outer_variable in outer_sequence:
# Outer loop
for inner_variable in inner_sequence:
# Code to repeat
Let us revisit the clock analogy in Python;
for hour in range(1, 4):
print(f"Hour {hour}")
for minute in range(1, 61):
print(f" Minute {minute}")
Here's what happens, step by step;
- Python starts with the outer loop and sets
hourto1. - Before moving to the next hour, Python enters the inner loop.
- The inner loop starts with
minute = 1and continues printing every minute until it reaches60. - Once all
60 minuteshave been printed, the inner loop finishes. - Python returns to the outer loop and updates
hourto2. - The inner loop starts again, printing minutes 1 through 60 for the second hour.
- The same process repeats for
hour = 3. - After the final hour has completed all
60 minutes, both loops end.
Result;
Hour 1
Minute 1
Minute 2
Minute 3
...
Minute 58
Minute 59
Minute 60
Hour 2
Minute 1
Minute 2
Minute 3
..
Minute 58
Minute 59
Minute 60
Hour 3
Minute 1
Minute 2
Minute 3
...
Minute 58
Minute 59
Minute 60
Notice that the minutes restart from 1 every time the hour changes. This is because the inner loop begins again from the start for every iteration of the outer loop, just as the minute hand completes a full revolution before the hour hand moves to the next hour.
Nested Loops Use cases
1. To find missing values (data cleaning)
Imagine you're checking a dataset before analysis. You need to examine every row, and within each row, inspect every column for missing or invalid values. This is a situation for nested loops because you're repeating one task (checking columns) inside another (moving through rows).
dataset = [
["HH001", 4, 25000, "Nairobi"],
["HH002", None, 18000, "Kisumu"],
["HH003", 6, None, "Mombasa"],
["HH004", 3, 32000, "Nakuru"]
]
for row in dataset:
household_id = row[0]
for value in row:
if value is None:
print(f"{household_id} has a missing value.")
The result:
HH002 has a missing value.
HH003 has a missing value.
2. To identify duplicate records (Data Quality)
Imagine you're cleaning survey data before analysis. Some respondents may have been entered twice. You can use nested for loop to compare every respondent against every other respondent to identify duplicate IDs.
respondent_ids = ["R001", "R002", "R003", "R002", "R004"]
for i in range(len(respondent_ids)):
for j in range(i + 1, len(respondent_ids)):
if respondent_ids[i] == respondent_ids[j]:
print(f"Duplicate respondent found: {respondent_ids[i]}")
The result:
Duplicate respondent found: R001
Duplicate respondent found: R002
i and j are index variables. The outer loop i selects one respondent at a time, while the inner loop j compares that respondent with every respondent that follows in the list. This ensures every unique pair is checked once, making it possible to detect duplicate IDs.
3. To find a specific value in your table (Data exploration)
dataset = [
[12, 25, 18],
[42, 33, 17],
[29, 56, 40]
]
target = 33
for row in range(len(dataset)):
for column in range(len(dataset[row])):
if dataset[row][column] == target:
print(f"{target}: Found at Row {row + 1}, Column {column + 1}")
The result:
33: Found at Row 2, Column 2
Although nested for loops are the most common when working with collections of data, you can also combine for and while loops. This is useful when you need to process a collection while repeating a task until a condition is met.
Here are some examples that incorporate both the for and while loops.
4. Data Validation (for + while)
You're collecting survey data. Every respondent must provide a valid age before you move on to the next respondent.
respondents = ["HH001", "HH002", "HH003"]
for respondent in respondents:
print(f"\nRecording data for {respondent}")
age = int(input("Enter age: "))
while age < 0 or age > 120:
print("Invalid age. Please enter an age between 1 and 120.")
age = int(input("Enter age: "))
print("Age recorded successfully.")
The for loop processes each respondent.
The while loop keeps asking until a valid value is entered.
The result:
Recording data for HH001
0: Invalid age. Please enter an age between 1 and 120.
-2: Invalid age. Please enter an age between 1 and 120.
21: Age recorded successfully.
Recording data for HH002
68: Age recorded successfully.
Recording data for HH003
178: Invalid age. Please enter an age between 1 and 120.
89: Age recorded successfully.
Limitations of Nested Loops
Like every other tool, nested loops have situations where they're less efficient.
As the amount of data grows, the inner loop must run for every iteration of the outer loop, increasing the total number of operations and potentially slowing down your program.
Imagine comparing every household in a dataset of 10,000 records with every other household to identify duplicates. Although this approach works, it performs a very large number of comparisons. As datasets grow, there are more efficient techniques that avoid checking every possible pair.
Nested loops are an excellent way to solve problems involving multiple levels of repetition. As we continue learning Python, we'll discover more efficient approaches for handling large datasets, particularly when working with libraries such as pandas.(We will cover these in a later series)
Conclusion
In this article, we've seen that nested loops are a practical way to solve real-world problems. Whether you're validating survey responses, checking for missing values, or comparing records, nested loops help you work through data that has multiple levels or repeated relationships.
As usual, keep experimenting by creating your own examples and thinking about tasks that involve one repeated process inside another. The more you practise, the more natural it will become to recognise when a nested loop is the right solution.
What's next?
"We've learned how to solve complex problems with loops, but what if we want to reuse that logic without writing it again?
In the next article, we'll explore functions and learn how to package reusable code into named blocks, making our programs less repetitive and easier to maintain.
Until then, happy coding!

Top comments (0)