Skip to content

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

Did a tutorial tell you to append a row, and Pandas say there is no such method?

sales.append({'region': 'East', 'revenue': 50}, ignore_index=True)
AttributeError: 'DataFrame' object has no attribute 'append'

Nothing is wrong with your code by the standards of what you were reading. DataFrame.append was deprecated in Pandas 1.4 and removed in 2.0, and a great deal of published material — including a lot of generated code — still uses it.

The direct translation is concat:

pd.concat([sales, pd.DataFrame([{'region': 'East', 'revenue': 50}])],
          ignore_index=True)
  region  revenue
0  North      100
1  South      250
2  North      175
3   East       50

Note that Python lists still have .append, and so do Series-of-lists. This error is specific to data frames.

Why it was removed, and why that matters to you

append encouraged a pattern that gets slow in a way beginners cannot see:

for row in source:
    df = df.append(row, ignore_index=True)      # do not do this

Every pass copied the entire frame. Ten rows is nothing; ten thousand rows is quadratic, and the program appears to hang for reasons that have nothing to do with the data.

Translating that loop to pd.concat inside the loop keeps the problem exactly:

for row in source:
    df = pd.concat([df, pd.DataFrame([row])])   # still copying every pass

The fix is not the function. It is building the rows first and combining once:

rows = []
for item in source:
    rows.append({'region': item.region, 'revenue': item.total})

df = pd.DataFrame(rows)

Python's list append is cheap, and the frame is built a single time. On a few thousand rows the difference is the difference between a noticeable pause and no pause at all.

If you are combining frames rather than rows

pd.concat takes a list, so collect the frames and concatenate once:

pd.concat([pd.read_csv(f) for f in files], ignore_index=True)

ignore_index=True renumbers the result, which is what you almost always want when the sources each start their index at zero. Without it you get repeated index labels, and that leads to the cannot reindex on an axis with duplicate labels error further down the pipeline.

The mistakes I see most often

Pinning Pandas to an old version to keep append. It buys time and costs more later; the replacement is a few lines.

Appending a bare dictionary to concat. pd.concat wants frames, so the dictionary needs wrapping in pd.DataFrame([...]) first.

Forgetting ignore_index=True. The result looks right and the index is a mess.

Practice

See concat in Pandas for combining frames, and DataFrame in Pandas for building one from a list of records.