向pandas数据框插入一行

250 投票
18 回答
908595 浏览
提问于 2025-04-18 10:12

我有一个数据表:

s1 = pd.Series([5, 6, 7])
s2 = pd.Series([7, 8, 9])

df = pd.DataFrame([list(s1), list(s2)],  columns =  ["A", "B", "C"])

   A  B  C
0  5  6  7
1  7  8  9

[2 rows x 3 columns]

我想在最上面加一行 [2, 3, 4],变成:

   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9

我试过 append()concat() 这两个函数,但不知道怎么才能做到。

怎么才能把一系列数据加到数据表里呢?

18 个回答

22

我写了一个简单的函数,可以在插入一行数据时提供更多的灵活性:

def insert_row(idx, df, df_insert):
    dfA = df.iloc[:idx, ]
    dfB = df.iloc[idx:, ]

    df = dfA.append(df_insert).append(dfB).reset_index(drop = True)

    return df

这个函数可以进一步简化为:

def insert_row(idx, df, df_insert):
    return df.iloc[:idx, ].append(df_insert).append(df.iloc[idx:, ]).reset_index(drop = True)

然后你可以像这样使用:

df = insert_row(2, df, df_new)

这里的 2 是你想在 df 中插入 df_new 的位置索引。

32

实现这个目标的一种方法是

>>> pd.DataFrame(np.array([[2, 3, 4]]), columns=['A', 'B', 'C']).append(df, ignore_index=True)
Out[330]: 
   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9

一般来说,添加数据框(dataframe)比添加序列(series)要简单。在你的情况下,因为你想让新行在“最上面”(从id开始),而且没有pd.prepend()这个函数,所以我先创建一个新的数据框,然后再把你旧的数据框加上去。

ignore_index会忽略你数据框中原来的索引,确保第一行的索引实际上是从1开始,而不是从0重新开始。

通常的免责声明:我认为... 添加行是一个效率比较低的操作。如果你在意性能,并且能够确保先创建一个带有正确(更长)索引的数据框,然后再将额外的行插入到数据框中,那你绝对应该这样做。见:

>>> index = np.array([0, 1, 2])
>>> df2 = pd.DataFrame(columns=['A', 'B', 'C'], index=index)
>>> df2.loc[0:1] = [list(s1), list(s2)]
>>> df2
Out[336]: 
     A    B    C
0    5    6    7
1    7    8    9
2  NaN  NaN  NaN
>>> df2 = pd.DataFrame(columns=['A', 'B', 'C'], index=index)
>>> df2.loc[1:] = [list(s1), list(s2)]

到目前为止,我们得到了你原来的df

>>> df2
Out[339]: 
     A    B    C
0  NaN  NaN  NaN
1    5    6    7
2    7    8    9

但现在你可以很容易地插入这一行。因为空间是预先分配的,这样效率更高。

>>> df2.loc[0] = np.array([2, 3, 4])
>>> df2
Out[341]: 
   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9
75

我不太确定你是怎么调用 concat() 的,但只要两个对象类型相同,它应该是可以正常工作的。也许问题在于你需要把第二个向量转换成数据框(dataframe)?使用你定义的那个数据框,下面的代码对我来说是有效的:

df2 = pd.DataFrame([[2,3,4]], columns=['A','B','C'])
pd.concat([df2, df])
78

测试了一些答案后,可以明显看出,对于大型数据表,使用 pd.concat() 更有效率。

在比较使用 dictlist 的性能时,发现 list 更高效,但对于小型数据表,使用 dict 也没问题,而且看起来更容易理解。


第一名 - pd.concat() + list

%%timeit
df = pd.DataFrame(columns=['a', 'b'])
for i in range(10000):
    df = pd.concat([pd.DataFrame([[1,2]], columns=df.columns), df], ignore_index=True)

每次循环耗时4.88秒 ± 47.1毫秒(7次运行的平均值 ± 标准差,每次运行1次)

第二名 - pd.append() + dict [在 v2.0.0 中已移除]

%%timeit

df = pd.DataFrame(columns=['a', 'b'])
for i in range(10000):
    df = df.append({'a': 1, 'b': 2}, ignore_index=True)

每次循环耗时10.2秒 ± 41.4毫秒(7次运行的平均值 ± 标准差,每次运行1次)

第三名 - pd.DataFrame().loc + index operations

%%timeit
df = pd.DataFrame(columns=['a','b'])
for i in range(10000):
    df.loc[-1] = [1,2]
    df.index = df.index + 1
    df = df.sort_index()

每次循环耗时17.5秒 ± 37.3毫秒(7次运行的平均值 ± 标准差,每次运行1次)

261

只需要用 loc 把行分配到特定的索引就可以了:

 df.loc[-1] = [2, 3, 4]  # adding a row
 df.index = df.index + 1  # shifting index
 df = df.sort_index()  # sorting by index

这样你就能得到你想要的结果:

    A  B  C
 0  2  3  4
 1  5  6  7
 2  7  8  9

想了解更多,可以查看Pandas的文档,里面有关于 索引和扩展设置 的详细说明。

撰写回答