在熊猫中同步两个大数据帧的最有效方法是什么?

Man*_*gia 3 python performance dataframe pandas

我想同步两个很长的数据帧,在这个用例中性能是关键。使用日期时间或时间戳按时间顺序对这两个数据帧进行索引(应该尽可能快地利用它)。

本例中提供了一种同步方式:

import pandas as pd
df1=pd.DataFrame({'A':[1,2,3,4,5,6], 'B':[1,5,3,4,5,7]}, index=pd.date_range('20140101 101501', freq='u', periods=6))
df2=pd.DataFrame({'D':[10,2,30,4,5,10], 'F':[1,5,3,4,5,70]}, index=pd.date_range('20140101 101501.000003', freq='u', periods=6))

# synch data frames
df3=df1.merge(df2, how='outer', right_index=True, left_index=True).fillna(method='ffill')
Run Code Online (Sandbox Code Playgroud)

我的问题是这是否是最有效的方法?如果有更快的方法来解决这个任务,我准备探索其他解决方案(例如使用 numpy 或 cython)。

谢谢

注意:时间戳通常不是等距间隔的(如上例所示),该方法也适用于这种情况

阅读答案后发表评论

我认为有很多用例既不对齐也不合并或加入帮助。关键是不要使用与 DB 相关的语义进行对齐(在我看来,这对于时间序列并不是那么相关)。对我来说,对齐意味着将系列 A 映射到 B 并有一种处理缺失值的方法(通常是采样和保持方法),对齐和连接会导致不想要的效果,例如由于连接而重复的几个时间戳。我仍然没有完美的解决方案,但似乎 np.searchsorted 可以提供帮助(它比使用多个调用来加入/对齐来完成我需要的要快得多)。到目前为止,我找不到熊猫的方法来做到这一点。

如何将 A 映射到 B 以便 B 使结果具有 A 和 B 的所有时间戳但没有重复(除了那些已经在 A 和 B 中的时间戳)?

另一个典型的用例是采样和保持同步,它可以通过如下有效的方式解决(同步 A 与 B,即为 A 中的每个时间戳取 B 中的相应值:

idx=np.searchsorted(B.index.values, A.index.values, side='right')-1
df=A.copy()
for i in B:
    df[i]=B[i].ix[idx].values
Run Code Online (Sandbox Code Playgroud)

结果 df 包含 A 的相同索引和 B 中的同步值。

有没有一种有效的方法可以直接在熊猫中做这样的事情?

Jef*_*eff 5

如果您需要同步,请使用align,文档在此处。否则合并是一个不错的选择。

In [18]: N=100000

In [19]: df1=pd.DataFrame({'A':[1,2,3,4,5,6]*N, 'B':[1,5,3,4,5,7]*N}, index=pd.date_range('20140101 101501', freq='u', periods=6*N))

In [20]: df2=pd.DataFrame({'D':[10,2,30,4,5,10]*N, 'F':[1,5,3,4,5,70]*N}, index=pd.date_range('20140101 101501.000003', freq='u', periods=6*N))

In [21]: %timeit df1.merge(df2, how='outer', right_index=True, left_index=True).fillna(method='ffill')
10 loops, best of 3: 69.3 ms per loop

In [22]: %timeit df1.align(df2)
10 loops, best of 3: 36.5 ms per loop

In [24]: pd.set_option('max_rows',10)

In [25]: x, y = df1.align(df2)

In [26]: x
Out[26]: 
                             A   B   D   F
2014-01-01 10:15:01          1   1 NaN NaN
2014-01-01 10:15:01.000001   2   5 NaN NaN
2014-01-01 10:15:01.000002   3   3 NaN NaN
2014-01-01 10:15:01.000003   4   4 NaN NaN
2014-01-01 10:15:01.000004   5   5 NaN NaN
...                         ..  ..  ..  ..
2014-01-01 10:15:01.599998   5   5 NaN NaN
2014-01-01 10:15:01.599999   6   7 NaN NaN
2014-01-01 10:15:01.600000 NaN NaN NaN NaN
2014-01-01 10:15:01.600001 NaN NaN NaN NaN
2014-01-01 10:15:01.600002 NaN NaN NaN NaN

[600003 rows x 4 columns]

In [27]: y
Out[27]: 
                             A   B   D   F
2014-01-01 10:15:01        NaN NaN NaN NaN
2014-01-01 10:15:01.000001 NaN NaN NaN NaN
2014-01-01 10:15:01.000002 NaN NaN NaN NaN
2014-01-01 10:15:01.000003 NaN NaN  10   1
2014-01-01 10:15:01.000004 NaN NaN   2   5
...                         ..  ..  ..  ..
2014-01-01 10:15:01.599998 NaN NaN   2   5
2014-01-01 10:15:01.599999 NaN NaN  30   3
2014-01-01 10:15:01.600000 NaN NaN   4   4
2014-01-01 10:15:01.600001 NaN NaN   5   5
2014-01-01 10:15:01.600002 NaN NaN  10  70

[600003 rows x 4 columns]
Run Code Online (Sandbox Code Playgroud)