Skip to content

Python Pandas: How to Append a Dictionary as a Row to a Pandas DataFrame

Learn the modern, performant ways to add single or multiple dictionary rows to a Pandas DataFrame after the .append() deprecation in Pandas 2.0, including .loc[] for single rows and pd.concat() for batch operations.

Adding rows from dictionaries is a common operation when collecting data incrementally, processing API responses, or building DataFrames record by record. Since the .append() method was removed in Pandas 2.0, it is important to know the modern alternatives that offer better performance and clearer intent.

In this guide, you will learn how to append single and multiple dictionary rows to a DataFrame, understand how each method handles mismatched columns, and avoid common performance pitfalls.

Using .loc[] for Single Row Addition

The most direct way to add a single dictionary as a new row is to assign it to a new index position using .loc[]:

import pandas as pd

df = pd.DataFrame({'Name': ['Alice', 'Bob'], 'Age': [25, 30]})

new_row = {'Name': 'Charlie', 'Age': 35}

df.loc[len(df)] = new_row

print(df)

Output:

      Name  Age
0    Alice   25
1      Bob   30
2  Charlie   35

This method modifies the DataFrame in place and is the fastest option for adding a single row.

Behavior with Non-Sequential Indices

When the existing index contains non-sequential values, len(df) still works but may produce an index that does not follow the existing pattern:

import pandas as pd

df = pd.DataFrame({'Name': ['Alice'], 'Age': [25]}, index=[100])

df.loc[len(df)] = {'Name': 'Bob', 'Age': 30}

print(df)

Output:

      Name  Age
100  Alice   25
1      Bob   30

Using pd.concat() for Multiple Rows

When you need to add several dictionary rows at once, convert them into a DataFrame and concatenate in a single operation:

import pandas as pd

df = pd.DataFrame({'Name': ['Alice'], 'Age': [25]})

new_rows = [
    {'Name': 'Bob', 'Age': 30},
    {'Name': 'Charlie', 'Age': 35}
]

df = pd.concat([df, pd.DataFrame(new_rows)], ignore_index=True)

print(df)

Output:

      Name  Age
0    Alice   25
1      Bob   30
2  Charlie   35

The ignore_index=True parameter resets the index so that all rows are numbered sequentially.

Why Batch Processing Matters

A critical mistake is placing pd.concat() inside a loop. Each call copies the entire existing DataFrame, resulting in quadratic time complexity:

import pandas as pd

df = pd.DataFrame(columns=['A'])
for i in range(1000):
    df = pd.concat([df, pd.DataFrame([{'A': i}])])  # Full copy every iteration

print(df)

Output:

      A
0     0
0     1
0     2
0     3
0     4
..  ...
0   995
0   996
0   997
0   998
0   999

[1000 rows x 1 columns]

The correct approach collects all dictionaries first and creates the DataFrame in one step:

import pandas as pd

rows = [{'A': i} for i in range(1000)]
df = pd.DataFrame(rows)  # Single operation

Output:

       A
0      0
1      1
2      2
3      3
4      4
..   ...
995  995
996  996
997  997
998  998
999  999

[1000 rows x 1 columns]

Why .append() Was Deprecated

If you encounter older code or tutorials, you may see the .append() method. It was removed in Pandas 2.0 and will raise an error:

import pandas as pd

df = pd.DataFrame({'Name': ['Alice', 'Bob'], 'Age': [25, 30]})

try:
    df = df.append({'Name': 'Charlie', 'Age': 35}, ignore_index=True)
except AttributeError as e:
    print(f"Error: {e}")

Output:

Error: 'DataFrame' object has no attribute 'append'

The method was deprecated for several reasons:

  • Performance: It created a full copy of the DataFrame on every call, making it extremely slow in loops.
  • Misleading name: Unlike Python's list.append(), it did not modify the DataFrame in place. It returned a new DataFrame, which was a frequent source of bugs.
  • Redundancy: pd.concat() already provided the same functionality with more flexibility.

Handling Mismatched Columns

When dictionary keys do not perfectly match the DataFrame columns, .loc[] and pd.concat() behave differently. Understanding this distinction helps you choose the right method for your situation.

.loc[] Ignores Extra Keys

Extra dictionary keys that do not correspond to existing columns are silently ignored:

import pandas as pd

df = pd.DataFrame({'Name': ['Alice'], 'Age': [25]})

df.loc[len(df)] = {'Name': 'Bob', 'Age': 30, 'City': 'NYC'}

print(df)

Output:

    Name  Age
0  Alice   25
1    Bob   30

The City value is discarded because the column does not exist in the DataFrame.

pd.concat() Creates New Columns

In contrast, pd.concat() adds any new columns from the dictionary, filling missing values with NaN for existing rows:

import pandas as pd

df = pd.DataFrame({'Name': ['Alice'], 'Age': [25]})

new_row = {'Name': 'Bob', 'Age': 30, 'City': 'NYC'}
df = pd.concat([df, pd.DataFrame([new_row])], ignore_index=True)

print(df)

Output:

    Name  Age City
0  Alice   25  NaN
1    Bob   30  NYC

Practical Example: Data Collection Loop

Here is a realistic pattern for collecting data from a function or API and building a DataFrame efficiently:

import pandas as pd

def fetch_record(record_id):
    """Simulate fetching a record from an external source."""
    return {
        'Timestamp': pd.Timestamp.now(),
        'Value': record_id * 10,
        'Status': 'OK' if record_id % 2 == 0 else 'Warning'
    }

collected_rows = []
for i in range(5):
    record = fetch_record(i)
    collected_rows.append(record)

df = pd.DataFrame(collected_rows)

print(df)

Output:

                   Timestamp  Value   Status
0 2026-02-16 22:04:03.957029      0       OK
1 2026-02-16 22:04:03.957081     10  Warning
2 2026-02-16 22:04:03.957085     20       OK
3 2026-02-16 22:04:03.957088     30  Warning
4 2026-02-16 22:04:03.957091     40       OK

This pattern keeps the loop lightweight by working only with plain dictionaries, deferring all DataFrame overhead to a single final step.

Quick Reference

Method Best For Modifies Original
df.loc[len(df)] = dict Single row addition Yes
pd.concat([df, pd.DataFrame(rows)]) Multiple rows at once No (returns new)
Collect in list, then pd.DataFrame() Loops with many iterations N/A (creates new)
Scenario Recommended Approach
Adding one row at a time df.loc[len(df)] = row_dict
Adding several rows at once pd.concat([df, pd.DataFrame(list_of_dicts)])
Building a DataFrame in a loop Collect dicts in a list, convert once at the end
  • Use .loc[len(df)] = dict for quick, in-place single-row additions.
  • For multiple rows or loop-based collection, always gather dictionaries in a list first and create the DataFrame in a single operation at the end.
  • This approach avoids the performance traps of repeated concatenation and keeps your code both fast and readable.
Navigation