Верторизация сопоставления двух фреймов данных сравнение datetimeindex

#python #python-3.x #pandas #dataframe

Вопрос:

У меня есть два кадра данных, упорядоченных по времени и времени, с использованием DatetimeIndex (метка времени), как показано ниже.

 df1
timestamp                            price  side  
2021-08-27 12:45:00.475100160 00:00  47.34  
2021-08-27 12:45:00.475100160 00:00  47.02 
2021-08-27 12:45:00.488067957 00:00  47.18 
2021-08-27 12:45:00.779297294 00:00  47.26 
2021-08-27 12:45:00.779297294 00:00  47.27 

df2
timestamp                            bid_price  ask_price   
2021-08-27 12:44:59.740064471 00:00  47.08  47.34
2021-08-27 12:45:00.475100160 00:00  47.02  47.34
2021-08-27 12:45:00.914411789 00:00  47.02  47.26
2021-08-27 12:45:00.915470114 00:00  47.02  47.34
 

Мне нужно сравнить индекс времени каждой строки в первом кадре данных (df1) с индексом времени даты второго кадра данных (df2). Первая строка в df2, которая имеет значение datetime, равное или меньшее значение datetimeindex строки в df1, будет использоваться для оценки столбцов df2.bid_price и df2.ask_price по сравнению со столбцом df1.цена. Если df1.цена == df2.bid_price, добавьте «Ставка» в столбец df1.side. Если df1.цена == df2.ask_price, добавьте » Ask » в столбец df1.side. Если df1.цена находится между dff2.ask_price и df2.bid_price, добавьте «Внутри» в столбец df1.side, иначе добавьте «Снаружи» в столбец df1.side.

Мой приведенный ниже код-наименее эффективный способ сделать это, выполнив итерацию по каждой строке df1 и сравнив ее с df2. Короче говоря, это занимает целую вечность, когда я начинаю просматривать что-либо более 10-20 тысяч строк. Я искал более эффективные способы сделать это.

 for x in range(len(df1)):
    price = df1.price.iloc[x]
    quote = df2[(df1.index[x] >= df2.index)][['bid_price','ask_price']].iloc[-1]
    if price == quote.bid_price:
        df1.side.iloc[x] = 'Bid'
    elif price == quote.ask_price:
        df1.side.iloc[x] = 'Ask'
    elif (price > quote.bid_price) amp; (price < quote.ask_price):
        df1.side.iloc[x] = 'Inside'
    else:
        df1.side.iloc[x] = 'Outside' 
 

Комментарии:

1. Я думаю, что вы могли бы использовать индекс из df1, чтобы найти нужную строку в df2 с помощью обратной интерполяции, а затем оттуда вы можете напрямую соединить их. Я попытаюсь откопать что-нибудь похожее, что я сделал некоторое время назад

2. Благодаря Дэвиду я надеюсь получить предложения о том, как значительно ускорить это, так как я использую время от времени 100 тыс. точек данных.

Ответ №1:

Вот рабочее решение, использующее pandas.merge_asof для объединения временных меток и numpy.select соответствия различным условиям:

 import numpy as np
df3 = pd.merge_asof(df1, df2, on='timestamp', direction='backward')
df3['side'] = np.select([df3['price']==df3['bid_price'], 
                         df3['price']==df3['ask_price'],
                         df3['price'].between(df3['bid_price'], df3['ask_price'])
                         ],
                        ['Bid', 'Ask', 'Inside'],
                        default='Outside'
                        )
 

выход:

 >>> df3
                            timestamp  price    side  bid_price  ask_price
0 2021-08-27 12:45:00.475100160 00:00  47.34     Ask      47.02      47.34
1 2021-08-27 12:45:00.475100160 00:00  47.02     Bid      47.02      47.34
2 2021-08-27 12:45:00.488067957 00:00  47.18  Inside      47.02      47.34
3 2021-08-27 12:45:00.779297294 00:00  47.26  Inside      47.02      47.34
4 2021-08-27 12:45:00.779297294 00:00  47.27  Inside      47.02      47.34
 

ПРИМЕЧАНИЕ. при необходимости вы можете удалить промежуточные столбцы: df3.drop(['bid_price', 'ask_price'], axis=1)

Комментарии:

1. спасибо, мозуэй. Это намного быстрее. Я подожду день или около того, чтобы посмотреть, есть ли у кого-нибудь еще какой-либо дополнительный ответ, прежде чем я приму и подам голос.