如何在 Pandas DataFrame 中添加一行?

concat, df.loc 都可以往 Pandas DataFrame 中添加行,但它们都存在性能的问题。本文在介绍前两种方法的基础上,着重介绍一种高性能的做法。

假设我们有这样一个 DataFrame

   seq
0    1
1    2
2    3

创建这个 DataFrame 的代码如下

df = pd.DataFrame({"seq":[1,2,3]})

这个 DataFrame 有3个元素,现在我们要往里面添加第4个元素,值为4。

concat 添加的方法如下

df2 = pd.DataFrame({"seq":[4]})
df = pd.concat([df, df2], ignore_index=True)

我们打印 df, 会发现它变成了这样

   seq
0    1
1    2
2    3
3    4

最下面这一行就是我们刚刚添加的行。

另一种往 DataFrame 添加行的方法,是用 df.loc 添加行,具体如下

df = pd.DataFrame({"seq":[1,2,3]})
df.loc[len(df)] ={"seq": 4}

我们打印一下 df,会发现 df 变成了

   seq
0    1
1    2
2    3
3    4

和上面的结果一模一样。

看上去 concatdf.loc 都可以往 DataFrame 里添加行,那它们的性能怎么样呢?

下面我们就来测试一下。

我们分别用 concatdf.loc 来构建一个10000行的 DataFrame。这个 DataFrame 长下面这样

       seq
0        0
1        1
2        2
3        3
4        4
...    ...
9995  9995
9996  9996
9997  9997
9998  9998
9999  9999

[10000 rows x 1 columns]

我们用添加行的方式来构造这样一个 DataFrame,并测试使用 concatdf.loc 各需要多少时间。

concat 性能

我们从空的 DataFrame 开始,用 concat 每次往里面添加一行,代码如下

import pandas as pd
import time

row_num = 10000
start = time.perf_counter()
df = pd.DataFrame({"seq": []})
for i in range(row_num):
    df1 = pd.DataFrame({"seq": [i]})
    df = pd.concat([df, df1])
end = time.perf_counter()
print("elapsed time: {}".format(end-start))

上面的代码使用 time.perf_counter() 记录了程序开始的时间和结束时间,两者的差就是程序运行的时间。

运行上面的程序会输出

elapsed time: 3.3971026440000003

df.loc 性能

同样的,我们测试一下 df.loc 添加行的性能

start = time.perf_counter()
df = pd.DataFrame({"seq": []})
for i in range(row_num):
    df.loc[i] = i
end = time.perf_counter()
print("elapsed time: {}".format(end-start))

运行上面的程序输出

elapsed time: 8.133717991

可以看到,无论是 concat 还是 df.loc ,性能都不高,都要花费数秒的时间。

那有没有性能高的做法呢?答案是有的。下面我们来介绍第三种方法,也是推荐的做法。

推荐的做法

这种方法是先把每一行的内容存成字典,把所有的字典添加到一个列表中,然后使用这个列表创建 df,代码如下

start = time.perf_counter()
rows = []
for i in range(row_num):
    rows.append({"seq": i})
df = pd.DataFrame(rows)
end = time.perf_counter()
print("elapsed time: {}".format(end-start))

运行程序输出

elapsed time: 0.007482828000000552

可以看到,这种做法的性能比 concat 提升了几百倍,比 df.loc 更是提升了千倍以上。