Pandas DataFrame concat和append的区别

117

我有一个包含一天tick数据的4个pandas数据框列表,希望将它们合并成一个数据框。然而,我无法理解concat在我的时间戳上的行为。请参见下面的详细信息:

data

[<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 35228 entries, 2013-03-28 00:00:07.089000+02:00 to 2013-03-28 18:59:20.357000+02:00
Data columns:
Price       4040  non-null values
Volume      4040  non-null values
BidQty      35228  non-null values
BidPrice    35228  non-null values
AskPrice    35228  non-null values
AskQty      35228  non-null values
dtypes: float64(6),
<class 'pandas.core.frame.DataFrame'>

DatetimeIndex: 33088 entries, 2013-04-01 00:03:17.047000+02:00 to 2013-04-01 18:59:58.175000+02:00
Data columns:
Price       3969  non-null values
Volume      3969  non-null values
BidQty      33088  non-null values
BidPrice    33088  non-null values
AskPrice    33088  non-null values
AskQty      33088  non-null values
dtypes: float64(6),
<class 'pandas.core.frame.DataFrame'>

DatetimeIndex: 50740 entries, 2013-04-02 00:03:27.470000+02:00 to 2013-04-02 18:59:58.172000+02:00
Data columns:
Price       7326  non-null values
Volume      7326  non-null values
BidQty      50740  non-null values
BidPrice    50740  non-null values
AskPrice    50740  non-null values
AskQty      50740  non-null values
dtypes: float64(6),
<class 'pandas.core.frame.DataFrame'>

DatetimeIndex: 60799 entries, 2013-04-03 00:03:06.994000+02:00 to 2013-04-03 18:59:58.180000+02:00
Data columns:
Price       8258  non-null values
Volume      8258  non-null values
BidQty      60799  non-null values
BidPrice    60799  non-null values
AskPrice    60799  non-null values
AskQty      60799  non-null values
dtypes: float64(6)]

使用append我得到:

pd.DataFrame().append(data)

<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 179855 entries, 2013-03-28 00:00:07.089000+02:00 to 2013-04-03 18:59:58.180000+02:00
Data columns:
AskPrice    179855  non-null values
AskQty      179855  non-null values
BidPrice    179855  non-null values
BidQty      179855  non-null values
Price       23593  non-null values
Volume      23593  non-null values
dtypes: float64(6)

使用concat,我得到:

pd.concat(data)

<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 179855 entries, 2013-03-27 22:00:07.089000+02:00 to 2013-04-03 16:59:58.180000+02:00
Data columns:
Price       23593  non-null values
Volume      23593  non-null values
BidQty      179855  non-null values
BidPrice    179855  non-null values
AskPrice    179855  non-null values
AskQty      179855  non-null values
dtypes: float64(6)

注意使用concat时索引如何改变。为什么会发生这种情况,我该如何使用concat来复制使用append获得的结果呢?(因为concat似乎更快:每个循环24.6毫秒对比每个循环3.02秒)

4个回答

186

Pandas concat与append、join及merge的区别

  • Concat提供了基于轴(所有行或所有列)连接的灵活性。

  • Append是concat的特殊情况(axis=0,join='outer'),现已弃用,请使用concat。

  • Join基于索引(由set_index设置),变量为['left','right','inner','couter']。

  • Merge基于两个数据框中任意特定列,这些列作为变量,如'left_on'、'right_on'和'on'。


栈方面怎么样? - skan

66

使用append和concat实现的结果是几乎相同的。区别在于空数据框。由于某种原因,这将导致严重减慢速度,但目前不确定为什么,需要在之后进行研究。以下是基本上复制了您所做内容的重新创建示例。

我几乎总是使用concat(虽然在这种情况下它们是等效的,除了空白帧);如果不使用空白帧,它们的速度将相同。

In [17]: df1 = pd.DataFrame(dict(A = range(10000)),index=pd.date_range('20130101',periods=10000,freq='s'))

In [18]: df1
Out[18]: 
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 10000 entries, 2013-01-01 00:00:00 to 2013-01-01 02:46:39
Freq: S
Data columns (total 1 columns):
A    10000  non-null values
dtypes: int64(1)

In [19]: df4 = pd.DataFrame()

The concat

In [20]: %timeit pd.concat([df1,df2,df3])
1000 loops, best of 3: 270 us per loop

This is equavalent of your append

In [21]: %timeit pd.concat([df4,df1,df2,df3])
10 loops, best of 

 3: 56.8 ms per loop

谢谢回复,这解释了计算时间的差异。请问为什么我的索引突然会随机更改呢? - JPBelanger
3
嗯,看起来是时区问题,我会提交一个错误报告。 - Jeff

59

tl;dr 始终使用 concat,因为

  1. append 已被弃用,而且
  2. 无论如何,在 concatappend 之间没有明显的区别(请参见下面的基准测试)。
我无法重现你的结果:我实施了一个小型基准测试(请在Gist上找到代码),以评估pandas的concatappend。我根据ssk08的评论更新了代码片段和结果 - 非常感谢!
该基准测试在Mac OS X 10.13系统上运行,使用Python 3.6.2和pandas 0.20.3。
使用ignore_index=False时,append稍微快一些;而使用ignore_index=True时,concat稍微快一些。

10
实际上,这是一个错误的评估。你的concat代码(pd.concat([df_small], ignore_index=True))并没有合并任何内容 - 这就是为什么我们看到了2倍的性能提升。尝试使用pd.concat([df_small, df_small], axis=0, ignore_index=True)进行计算 - 这就是append所做的,你会发现性能提升消失了。 - ssk08
11
@ssk08非常感谢您的贡献!我已经相应地更新了我的答案 - 您是完全正确的! - Michael Dorner

17

还有一件事情需要记住,在Pandas中的APPEND()方法并不会修改原对象,而是创建一个新的合并数据的对象。由于涉及到创建和数据缓存,其性能并不好。做多次APPEND操作时最好使用CONCAT()函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接