Панды, заполните ячейку следующим условным значением на основе нескольких столбцов - PullRequest
2 голосов
/ 03 октября 2019

У меня есть датафрейм в соответствии с приведенными ниже линиями для анализа данных о запасах:

    timestamp                    Price      Exit Price
1   2019-09-29 15:33:00          14         
2   2019-09-29 15:34:00          15          
3   2019-09-29 15:35:00          14         
4   2019-09-29 15:36:00          17         
5   2019-09-29 15:37:00          20        

Я пытаюсь протестировать стратегию, поэтому хочу заполнить столбец цены выхода с последующимзначение столбца цены, когда выполняется первая строка с любым из следующих условий:

  1. Разница во времени между отметкой времени текущей строки и отметкой времени сравнения больше или равна X минутам.
  2. Разница в процентах между текущей ценой строки и ценой строки сравнения больше, чем Y процентов

Так, например, если число минут равно 2, а возврат равен 10%, таблица должна быть заполненаследующим образом:

    timestamp                    Price      Exit Price
1   2019-09-29 15:33:00          14         14<-- From Row 3 because 2 minutes passed
2   2019-09-29 15:34:00          15         17<-- From Row 4, both conditions satisfied
3   2019-09-29 15:35:00          14         17<-- From Row 4, difference greater than 10%
4   2019-09-29 15:36:00          17         20
5   2019-09-29 15:37:00          20         Nan

Я думал о реализации решения, подобного этому:

customFilter(row):
    results = df[
                (df['timestamp'] > row['timestamp']) &
                (
                  (df['timestamp'] <= (row['timestamp']+pd.timedelta('2m')) |
                  (df['price'] > row['price']*1.1)
                )
             ]

     if results.shape[0] > 0:
         return results['price'].first()

     return nan

df['Exit Price'] = df.apply(lambda x: customFilter(x), axis = 1)

Вопрос в том, есть ли лучший способ сделать это? Это не самый эффективный или быстрый способ, особенно если я увеличу размер своего набора данных.

Ответы [ 2 ]

1 голос
/ 03 октября 2019

Вот как вы можете сделать это, используя функцию вещания numpy

df = pd.DataFrame([('2019-09-29 15:33:00', '14'), ('2019-09-29 15:34:00', '15'), ('2019-09-29 15:35:00', '14'), ('2019-09-29 15:36:00', '17'), ('2019-09-29 15:37:00', '20')], columns=('timestamp', 'Price'))
df.timestamp = pd.to_datetime(df.timestamp)
df.Price = df.Price.astype(np.int)

price = df.Price.values
timestamp = df["timestamp"].values

## compare each pair of row with each other for the condition
## np.newaxis is used so that rows are repeated in column direction creating a matrix of len(rows)*len(rows)
cond = ((timestamp+pd.Timedelta("2m"))<=timestamp[:, np.newaxis]) | \
((price[:, np.newaxis] - price)/price >=0.1)

## argmax will give 1st index matching the cond
df.loc[cond.argmax(axis=0)>0, "Extra Price"] = price[cond.argmax(axis=0)[cond.argmax(axis=0)>0]]
display(df)

Результат

timestamp   Price   Extra Price
0   2019-09-29 15:33:00 14  14.0
1   2019-09-29 15:34:00 15  17.0
2   2019-09-29 15:35:00 14  17.0
3   2019-09-29 15:36:00 17  20.0
4   2019-09-29 15:37:00 20  NaN
1 голос
/ 03 октября 2019

IICU, это то, что вам нужно.

from datetime import timedelta
df['timestamp'] = pd.to_datetime(df['timestamp'])

E_Price=[]
time_diff = df['timestamp'].apply(lambda x: x >= (df['timestamp']+timedelta(minutes=2)))
price_diff = df['Price'].apply(lambda x: x >= (df['Price']*1.1))
for i in range(len(df)):
    check = (time_diff|price_diff)[i]
    ind = check.idxmax()
    if ind != 0:
        val = df.iloc[ind,1]
    else:
        val = np.nan
    E_Price.append(val)    

df['Exit_Price'] = E_Price
df['Exit_Price'] = df.Exit_Price.astype(pd.Int32Dtype())
print(df)

Вывод

            timestamp   Price   Exit_Price
0   2019-09-29 15:33:00     14  14
1   2019-09-29 15:34:00     15  17
2   2019-09-29 15:35:00     14  17
3   2019-09-29 15:36:00     17  20
4   2019-09-29 15:37:00     20  NaN
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...