错误“‘DataFrame’对象没有属性‘append’”

问题描述 投票:0回答:3

我试图将字典附加到 DataFrame 对象,但出现以下错误:

AttributeError:“DataFrame”对象没有属性“append”

据我所知,DataFrame确实有“append”方法。

代码片段:

df = pd.DataFrame(df).append(new_row, ignore_index=True)

我期待字典

new_row
被添加为新行。

python pandas dataframe attributeerror
3个回答
120
投票

从 pandas 2.0 开始,

append
(之前已弃用)已删除

您需要使用

concat
(对于大多数应用程序):

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

正如@cottontail所指出的,也可以使用

loc
,尽管这仅在新索引尚未存在于DataFrame中时才有效(通常,如果索引是
RangeIndex,则会出现这种情况) 

df.loc[len(df)] = new_row # only use with a RangeIndex!

为什么被删除?

我们经常看到 的新用户尝试像使用纯 Python 一样进行编码。他们使用

iterrows
来访问循环中的项目(请参阅 here 为什么不应该),或者以类似于 python
append
 的方式使用 
list.append

然而,正如pandas问题#35407中所述,pandas的

append
list.append
实际上不是同一件事
list.append
已就位,而 pandas 的
append
创建了一个新的 DataFrame:

我认为我们应该弃用 Series.append 和 DataFrame.append。 他们正在与 list.append 进行类比,但这是一个糟糕的类比 因为行为尚未(也不可能)到位。数据为 需要复制索引和值才能创建结果。

这些显然也是流行的方法。 DataFrame.append 就在附近 我们的 API 文档中访问量排名第十的页面。

除非我弄错了,否则用户最好建立一个列表 值并将它们传递给构造函数,或者构建一个列表 NDFrames 后跟一个 concat。

因此,虽然

list.append
在循环的每一步都是 摊销 O(1),但 pandas'
append
O(n)
,使得重复插入时效率低下

如果我需要重复该过程怎么办?

重复使用

append
concat
不是一个好主意(这具有 二次行为,因为它为每个步骤创建一个新的 DataFrame)。

在这种情况下,新项目应收集在列表中,并在循环结束时转换为

DataFrame
并最终连接到原始
DataFrame

lst = []

for new_row in items_generation_logic:
    lst.append(new_row)

# create extension
df_extended = pd.DataFrame(lst, columns=['A', 'B', 'C'])
# or columns=df.columns if identical columns

# concatenate to original
out = pd.concat([df, df_extended])

17
投票

如果是单行

loc
也可以完成这项工作。

df.loc[len(df)] = new_row

通过

loc
调用,数据帧会使用索引标签
len(df)
进行放大,仅当索引为
RangeIndex
时才有意义;如果未将显式索引传递给数据帧构造函数,则默认创建
RangeIndex

一个工作示例:

df = pd.DataFrame({'A': range(3), 'B': list('abc')})
df.loc[len(df)] = [4, 'd']
df.loc[len(df)] = {'A': 5, 'B': 'e'}
df.loc[len(df)] = pd.Series({'A': 6, 'B': 'f'})


也就是说,如果您要使用

DataFrame.append
concat
loc
在循环中放大数据框,请考虑重写代码以放大 Python 列表并构造一次数据框。

正如 @mozway 所指出的,放大 pandas 数据帧具有 O(n^2) 复杂度,因为在每次迭代中,必须读取和复制整个数据帧。下面的 perfplot 显示了相对于一次串联的运行时差异。1 正如您所看到的,两种扩大数据帧的方法都比扩大列表和构建一次数据帧要慢得多(例如,对于具有 10k 行的数据帧,循环中的

concat
大约慢 800 倍,循环中的
loc
大约慢 1600 倍)。

1 用于生成性能图的代码:

import pandas as pd
import perfplot

def concat_loop(lst):
    df = pd.DataFrame(columns=['A', 'B'])
    for dic in lst:
        df = pd.concat([df, pd.DataFrame([dic])], ignore_index=True)
    return df.infer_objects()
    
def concat_once(lst):
    df = pd.DataFrame(columns=['A', 'B'])
    df = pd.concat([df, pd.DataFrame(lst)], ignore_index=True)
    return df.infer_objects()

def loc_loop(lst):
    df = pd.DataFrame(columns=['A', 'B'])
    for dic in lst:
        df.loc[len(df)] = dic
    return df


perfplot.plot(
    setup=lambda n: [{'A': i, 'B': 'a'*(i%5+1)} for i in range(n)],
    kernels=[concat_loop, concat_once, loc_loop],
    labels= ['concat in a loop', 'concat once', 'loc in a loop'],
    n_range=[2**k for k in range(16)],
    xlabel='Length of dataframe',
    title='Enlarging a dataframe in a loop',
    relative_to=1,
    equality_check=pd.DataFrame.equals);

13
投票

免责声明:这个答案似乎很受欢迎,但建议的方法不应该使用

append
更改
_append
_append
是私有 内部 方法,
append
已从 pandas API 删除。声明“pandas 中的 append
 方法看起来类似于 python 中的 list.append。这就是为什么 pandas 中的append 方法现在修改为 
_append
。”
是完全不正确的,前导
_
 只意味着一件事,该方法是 
private 并且不打算在 pandas 的内部代码之外使用。


在新版本的

Pandas中,append

方法更改为
_append
,您可以简单地使用
_append
代替
append
,即
df._append(df2)

df = df1._append(df2,ignore_index=True)

为什么变了?

pandas 中的

append

 方法看起来与 python 中的 list.append 类似。这就是为什么 pandas 中的append 方法现在修改为 
_append

    

© www.soinside.com 2019 - 2024. All rights reserved.