1. 程式人生 > >【python】詳解pandas庫的pd.merge_ordered與pd.merge_asof

【python】詳解pandas庫的pd.merge_ordered與pd.merge_asof

  • merge_ordered:
    函式允許組合時間序列和其他有序資料。 特別是它有一個可選的fill_method關鍵字來填充/插入缺失的資料。
import pandas as pd

left = pd.DataFrame({'k': ['K0', 'K1', 'K1', 'K2'],
                   'lv': [1, 2, 3, 4],
                   's': ['a', 'b', 'c', 'd']})
right = pd.DataFrame({'k': ['K1', 'K2', 'K4'],
                   'rv': [1, 2, 3]})
pd.merge_ordered(left, right, fill_method='ffill', left_by='s')
# 當merge沒有指定連結鍵時,預設從left和right列的交集將被推斷為連線鍵
Out[2]: 
     k   lv  s   rv
0   K0  1.0  a  NaN
1   K1  1.0  a  1.0
2   K2  1.0  a  2.0
3   K4  1.0  a  3.0
4   K1  2.0  b  1.0
5   K2  2.0  b  2.0
6   K4  2.0  b  3.0
7   K1  3.0  c  1.0
8   K2  3.0  c  2.0
9   K4  3.0  c  3.0
10  K1  NaN  d  1.0
11  K2  4.0  d  2.0
12  K4  4.0  d  3.0
  • merge_asof
    除了我們匹配最近的鍵而不是相等的鍵之外,其他的都類似於有序的left-join 。 對於左側DataFrame中的每一行,我們選擇右側DataFrame中on鍵對應的值小於left的鍵對應的值的最後一行。 兩個DataFrame必須按鍵排序。
trades = pd.DataFrame({
     'time': pd.to_datetime(['20160525 13:30:00.023',
                             '20160525 13:30:00.038',
                             '20160525 13:30:00.048',
                             '20160525 13:30:00.048',
                             '20160525 13:30:00.048']),
     'ticker': ['MSFT', 'MSFT',
                'GOOG', 'GOOG', 'AAPL'],
     'price': [51.95, 51.95,
                 720.77, 720.92, 98.00],
     'quantity': [75, 155,
                    100, 100, 100]},
      columns=['time', 'ticker', 'price', 'quantity'])
  

quotes = pd.DataFrame({
      'time': pd.to_datetime(['20160525 13:30:00.023',
                              '20160525 13:30:00.023',
                              '20160525 13:30:00.030',
                              '20160525 13:30:00.041',
                              '20160525 13:30:00.048',
                              '20160525 13:30:00.049',
                              '20160525 13:30:00.072',
                              '20160525 13:30:00.075']),
     'ticker': ['GOOG', 'MSFT', 'MSFT',
                  'MSFT', 'GOOG', 'AAPL', 'GOOG',
                'MSFT'],
     'bid': [720.50, 51.95, 51.97, 51.99,
               720.50, 97.99, 720.50, 52.01],
     'ask': [720.93, 51.96, 51.98, 52.00,
                720.93, 98.01, 720.88, 52.03]},
     columns=['time', 'ticker', 'bid', 'ask'])


trades
Out[4]: 
                     time ticker   price  quantity
0 2016-05-25 13:30:00.023   MSFT   51.95        75
1 2016-05-25 13:30:00.038   MSFT   51.95       155
2 2016-05-25 13:30:00.048   GOOG  720.77       100
3 2016-05-25 13:30:00.048   GOOG  720.92       100
4 2016-05-25 13:30:00.048   AAPL   98.00       100

quotes
Out[5]: 
                     time ticker     bid     ask
0 2016-05-25 13:30:00.023   GOOG  720.50  720.93
1 2016-05-25 13:30:00.023   MSFT   51.95   51.96
2 2016-05-25 13:30:00.030   MSFT   51.97   51.98
3 2016-05-25 13:30:00.041   MSFT   51.99   52.00
4 2016-05-25 13:30:00.048   GOOG  720.50  720.93
5 2016-05-25 13:30:00.049   AAPL   97.99   98.01
6 2016-05-25 13:30:00.072   GOOG  720.50  720.88
7 2016-05-25 13:30:00.075   MSFT   52.01   52.03

下面Oder的順序是按照ticker排序,連線鍵是time:

pd.merge_asof(trades, quotes,
             on='time',
             by='ticker')
Out[6]: 
                     time ticker   price  quantity     bid     ask
0 2016-05-25 13:30:00.023   MSFT   51.95        75   51.95   51.96
1 2016-05-25 13:30:00.038   MSFT   51.95       155   51.97   51.98
2 2016-05-25 13:30:00.048   GOOG  720.77       100  720.50  720.93
3 2016-05-25 13:30:00.048   GOOG  720.92       100  720.50  720.93
4 2016-05-25 13:30:00.048   AAPL   98.00       100     NaN     NaN

可以看出相當於left_join,只根據left的key進行merge。值得注意的是,right對應的值的time最大不能超過left的time,比如left中 2016-05-25 13:30:00.038 MSFT,那麼拼接的right對應的時間最大是 2016-05-25 13:30:00.030 MSFT 51.97 51.98。APPL在right中就沒有對應的值。

  • tolerance:新增容忍的時間差;例如我們僅在報價時間和交易時間之間的2ms內,意味著交易的時間減去10ms再進行比較
pd.merge_asof(trades, quotes,on='time',by='ticker',tolerance=pd.Timedelta('2ms'))
Out[7]: 
                     time ticker   price  quantity     bid     ask
0 2016-05-25 13:30:00.023   MSFT   51.95        75   51.95   51.96
1 2016-05-25 13:30:00.038   MSFT   51.95       155     NaN     NaN
2 2016-05-25 13:30:00.048   GOOG  720.77       100  720.50  720.93
3 2016-05-25 13:30:00.048   GOOG  720.92       100  720.50  720.93
4 2016-05-25 13:30:00.048   AAPL   98.00       100     NaN     NaN

我們僅在報價時間和交易時間之間的10ms內,我們按時排除完全匹配。 請注意,雖然我們排除了(報價quote)完全匹配,但先前的quote會傳播到該時間點。

pd.merge_asof(trades, quotes,
                  on='time',
                  by='ticker',
                  tolerance=pd.Timedelta('10ms'),
                  allow_exact_matches=False)
Out[8]: 
                     time ticker   price  quantity    bid    ask
0 2016-05-25 13:30:00.023   MSFT   51.95        75    NaN    NaN
1 2016-05-25 13:30:00.038   MSFT   51.95       155  51.97  51.98
2 2016-05-25 13:30:00.048   GOOG  720.77       100    NaN    NaN
3 2016-05-25 13:30:00.048   GOOG  720.92       100    NaN    NaN
4 2016-05-25 13:30:00.048   AAPL   98.00       100    NaN    NaN