Question

How to Iterate Over Rows in a Pandas DataFrame in Python

pythonpandasdataframeloops

Question

I have a pandas DataFrame named df:

import pandas as pd

df = pd.DataFrame({
    'c1': [10, 11, 12],
    'c2': [100, 110, 120]
})

It looks like this:

   c1   c2
0  10  100
1  11  110
2  12  120

How can I iterate over the rows of this DataFrame?

For each row, I want to access its cell values by column name, like this:

for row in df.rows:
    print(row['c1'], row['c2'])

I found similar examples suggesting these approaches:

for date, row in df.T.iteritems():
    pass

and

for row in df.iterrows():
    pass

However, I do not understand what the row object actually is in these examples, or how to use it correctly.

Short Answer

By the end of this page, you will understand how row iteration works in a Pandas DataFrame, what iterrows() returns, how to access values by column name, and when to prefer alternatives like itertuples() or vectorized Pandas operations.

Concept

In Pandas, a DataFrame is a table-like data structure with rows and columns. Each column has a name, and each row has an index.

When you iterate over a DataFrame row by row, Pandas does not give you a plain dictionary automatically. Instead, the exact object depends on the method you use:

  • df.iterrows() returns pairs of (index, row)
  • row is a Pandas Series
  • You can access values from that Series using column names like row['c1']

Example:

for index, row in df.iterrows():
    print(index, row['c1'], row['c2'])

Why this matters:

  • Beginners often expect row to be a dictionary
  • In reality, row behaves more like a labeled one-dimensional array
  • Knowing this helps you read and write DataFrame code correctly

Also, row iteration is usually not the fastest Pandas approach. Pandas is designed for vectorized operations, which means working with entire columns or the whole DataFrame at once.

For example, instead of looping:

for index, row in df.iterrows():
    print(row['c1'] + row['c2'])

You can often do:

df['sum'] = df['c1'] + df['c2']

That is shorter, faster, and more idiomatic in Pandas.

Mental Model

Think of a DataFrame as a spreadsheet.

  • The DataFrame is the whole sheet
  • A row is one horizontal line in the sheet
  • A Series is like taking one row and turning it into a labeled list

So when you use iterrows(), Pandas hands you:

  1. the row label (index)
  2. a row object (Series) where:
    • the labels are the column names
    • the values are the cell values in that row

It is similar to receiving this for the first row:

index = 0
row = pd.Series({'c1': 10, 'c2': 100})

Then you can do:

row['c1']
row['c2']

So the main idea is: a row from iterrows() is a Series with column names as keys.

Take Quiz

Syntax and Examples

Basic row iteration with iterrows()

import pandas as pd

df = pd.DataFrame({
    'c1': [10, 11, 12],
    'c2': [100, 110, 120]
})

for index, row in df.iterrows():
    print(index, row['c1'], row['c2'])

Output:

0 10 100
1 11 110
2 12 120

What is happening?

  • df.iterrows() produces one row at a time
  • Each item is a pair: (index, row)
  • index is the row label (0, 1, 2)
  • row is a Series

Inspect the row type

for index, row in df.iterrows():
    print(type(row))
    print(row)
    break

Output will be similar to:

<class 'pandas.core.series.Series'>
c1     10
c2    100
Name: 0, dtype: int64

This shows that each row is a Series whose index contains the column names.

Access by column name

for index, row in df.iterrows():
    value1 = row['c1']
    value2 = row['c2']
    print(f"c1={value1}, c2={value2}")

Faster alternative: itertuples()

for row in df.itertuples(index=True):
    print(row.Index, row.c1, row.c2)

Output:

0 10 100
1 11 110
2 12 120

itertuples() is often faster than iterrows() and is commonly preferred when you truly need to loop.

Step by Step Execution

Consider this code:

import pandas as pd

df = pd.DataFrame({
    'c1': [10, 11],
    'c2': [100, 110]
})

for index, row in df.iterrows():
    print('index:', index)
    print('c1:', row['c1'])
    print('c2:', row['c2'])

Step-by-step

  1. Pandas creates a DataFrame with two columns: c1 and c2.

  2. df.iterrows() starts producing rows one at a time.

  3. On the first loop:

    • index is 0
    • row is a Series like:
    c1     10
    c2    100
    Name: 0, dtype: int64
    
  4. row['c1'] returns 10

  5. row['c2'] returns 100

  6. On the second loop:

    • index is 1
    • row['c1'] is 11
    • row['c2'] is 110

Important detail

This means iterrows() does not return only the row. It returns:

(index, row)

So this is wrong:

for row in df.iterrows():
    print(row['c1'])

Because row is actually the whole tuple (index, Series).

Correct version:

for index, row in df.iterrows():
    print(row['c1'])

Real World Use Cases

Row iteration is useful when you need to process records one at a time, especially when each row triggers some external action.

Common practical examples

  • Sending API requests

    • Each row contains user data or product data
    • You loop through rows and send one request per record
  • Generating files or messages

    • Each row becomes an email, report line, or JSON payload
  • Data validation

    • Check each row for missing or invalid combinations of values
  • Database migration scripts

    • Read rows from a CSV into a DataFrame, then insert or transform records one by one
  • Logging or auditing

    • Compare fields in each row and record issues

Example: building payloads

for _, row in df.iterrows():
    payload = {
        'amount': row['c1'],
        'total': row['c2']
    }
    print(payload)

But if your goal is calculation or transformation inside Pandas, prefer vectorized code when possible.

Take Quiz

Real Codebase Usage

In real projects, developers usually avoid row iteration unless they truly need it.

Common patterns

1. Vectorized transformations first

df['difference'] = df['c2'] - df['c1']

This is preferred over looping.

2. Use iterrows() for readability when row labels matter

for index, row in df.iterrows():
    if row['c1'] < 0:
        print(f"Invalid row at index {index}")

3. Use itertuples() for performance

for row in df.itertuples(index=False):
    print(row.c1, row.c2)

4. Guard clauses during row processing

for _, row in df.iterrows():
    if pd.isna(row['c1']):
        continue
    print(row['c1'])

5. Build Python objects from rows

records = []
for _, row in df.iterrows():
    records.append({
        'c1': row['c1'],
        'c2': row['c2']
    })

6. Validation and error handling

for index, row in df.iterrows():
    try:
        result = row['c2'] / row['c1']
        print(result)
    except ZeroDivisionError:
        print(f"Row {index} has c1 = 0")

These are realistic situations where looping is acceptable because the work per row is more than simple arithmetic.

Common Mistakes

1. Forgetting that iterrows() returns (index, row)

Broken code:

for row in df.iterrows():
    print(row['c1'])

Why it fails:

  • row is actually a tuple, not a Series

Correct code:

for index, row in df.iterrows():
    print(row['c1'])

2. Expecting row to be a dictionary

A row from iterrows() behaves similarly to a mapping because you can use column names, but it is a Series, not a plain dict.

for _, row in df.iterrows():
    print(type(row))

3. Modifying row and expecting the DataFrame to change

Broken expectation:

for _, row in df.iterrows():
    row['c1'] = 999

This often does not update the original DataFrame as expected.

Better approach:

df.loc[:, 'c1'] = 999

Or if you must update specific rows:

for index, row in df.iterrows():
    df.loc[index, 'c1'] = row['c1'] * 2

4. Using row loops for simple column math

Less ideal:

for index, row in df.iterrows():
    df.loc[index, 'sum'] = row['c1'] + row['c2']

Better:

df['sum'] = df['c1'] + df['c2']

5. Using df.T.iteritems() without understanding it

df.T transposes the DataFrame, swapping rows and columns. That changes the structure and usually is not the clearest way to iterate rows.

Prefer:

for index, row in df.iterrows():
    print(row['c1'])

6. Assuming iterrows() preserves exact dtypes per row

Because rows are returned as Series, data types may be converted in ways beginners do not expect. If dtype fidelity or speed matters, itertuples() is often better.

Comparisons

Row iteration methods in Pandas

MethodWhat it returnsAccess styleSpeedBest use
iterrows()(index, Series)row['c1']SlowerBeginner-friendly row access by column name
itertuples()named tuplesrow.c1FasterPerformance-sensitive loops
Vectorized operationswhole columns/arraysdf['c1'] + df['c2']FastestMost calculations and transformations

iterrows() vs itertuples()

iterrows()

Pros:

  • Easy to understand
  • Access by column name with row['column']
  • Good for learning and simple scripts

Cons:

  • Slower
  • Returns Series objects
  • Can change dtypes row by row

itertuples()

Pros:

  • Faster
  • Cleaner for read-only row access
  • Often preferred in production loops

Cons:

  • Access is usually attribute-based, like row.c1
  • Slightly less flexible if you strongly want dictionary-like access

Looping vs vectorized code

ApproachExampleRecommended?
Row loopfor _, row in df.iterrows(): ...Only when needed
Vectorizeddf['sum'] = df['c1'] + df['c2']Yes, usually

If your task is column-based math, filtering, replacing, or transformation, vectorized Pandas code is usually the right choice.

Take Quiz

Cheat Sheet

Quick reference

Iterate with iterrows()

for index, row in df.iterrows():
    print(index, row['c1'], row['c2'])
  • Returns (index, row)
  • row is a pandas.Series
  • Access values by column name: row['column_name']

Ignore the index if you do not need it

for _, row in df.iterrows():
    print(row['c1'])

Faster row iteration with itertuples()

for row in df.itertuples(index=False):
    print(row.c1, row.c2)

Best for calculations: vectorized code

df['sum'] = df['c1'] + df['c2']

Rules to remember

  • iterrows() gives you index + row
  • row is a Series, not a dict
  • Do not rely on modifying row to update the DataFrame
  • Prefer itertuples() for faster loops
  • Prefer vectorized operations when possible

Common patterns

for index, row in df.iterrows():
    if row['c1'] > 10:
        print(index)
for row in df.itertuples():
    print(row.Index, row.c1)

Edge case

If column names are not valid Python identifiers, itertuples() attribute access can be less convenient. In that case, iterrows() may feel easier.

FAQ

What does df.iterrows() return in Pandas?

It returns an iterator of (index, row) pairs. The row value is a Pandas Series.

How do I access a column value while iterating rows?

With iterrows(), use the column name:

for _, row in df.iterrows():
    print(row['c1'])

Is iterrows() the best way to loop through a DataFrame?

Not usually. It is fine for simple row-by-row tasks, but vectorized operations or itertuples() are often better.

What is the difference between iterrows() and itertuples()?

iterrows() returns Series objects and allows row['c1']. itertuples() returns named tuples and is usually faster.

Can I modify the DataFrame by changing row inside iterrows()?

Do not rely on that. Update the DataFrame directly with .loc or use vectorized assignments.

Why do some examples use for _, row in df.iterrows()?

The underscore means the index is being ignored because it is not needed.

Should I use df.T.iteritems() to iterate rows?

Usually no. It transposes the DataFrame first, which is less direct and often less clear than using iterrows() or itertuples().

Take Quiz

Mini Project

Description

Build a small script that reads a Pandas DataFrame of products and prints a summary for each row. This demonstrates how to iterate through rows, access values by column name, and decide when a loop is appropriate.

Goal

Create a script that loops through a DataFrame and prints a formatted message for each product using values from named columns.

Requirements

[ "Create a DataFrame with columns named product, price, and quantity", "Iterate through each row using a Pandas row iteration method", "Access each value by its column name or row attribute", "Print a sentence showing the product name and total value for that row" ]

Take Quiz

Keep learning

Related questions

View more