Более быстрый способ сделать вычисления t-1 в пандах - PullRequest
1 голос
/ 28 октября 2019

У меня есть df с 250 000+ строк. У меня есть несколько полей, которые зависят от значений t-1. Это очень легко сделать в Excel, но не уверен, какой самый эффективный способ сделать это в пандах. В настоящее время я устанавливаю значение t [0], затем использую цикл for, чтобы сделать все остальное, но это невероятно медленно. Есть ли более быстрый способ сделать это?

Любая помощь будет принята с благодарностью!

код ниже

import pandas as pd
import numpy as np
import math
import datetime
from scipy.optimize import minimize

df = pd.DataFrame({
    'Time': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
    'Price': [44, 100, 40, 110, 77, 109, 65, 93, 89, 73]})

# Create Empty Columns
df[['Qty', 'Buy', 'Sell', 'Cost', 'Rev']] = pd.DataFrame([[0.00, 0.00, 0.00, 0.00, 0.00]], index=df.index)

# Initial Values
buy_price = 50
sell_price = 100

# Set Values at Time 0
df.at[0, 'Qty'] = 0
df.at[0, 'Buy'] = np.where(df.at[0, 'Price'] < buy_price, min(30 - df.at[0, 'Qty'], 10), 0)
df.at[0, 'Sell'] = np.where(df.at[0, 'Price'] > sell_price, min(df.at[0, 'Qty'], 10), 0)
df.at[0, 'Cost'] = df.at[0, 'Buy'] * df.at[0, 'Price']
df.at[0, 'Rev'] = df.at[0, 'Sell'] * df.at[0, 'Price']

# Set Remaining Values
for t in range(1, len(df)):
    df.at[t, 'Qty'] = df.at[t-1, 'Qty'] + df.at[t-1, 'Buy'] - df.at[t-1, 'Sell']
    df.at[t, 'Buy'] = np.where(df.at[t, 'Price'] < buy_price, min(30 - df.at[t, 'Qty'], 10), 0)
    df.at[t, 'Sell'] = np.where(df.at[t, 'Price'] > sell_price, min(df.at[t, 'Qty'], 10), 0)
    df.at[t, 'Cost'] = df.at[t, 'Buy'] * df.at[t, 'Price']
    df.at[t, 'Rev'] = df.at[t, 'Sell'] * df.at[t, 'Price']

Я посмотрел это предыдущий пост, что было похоже, но я не думаю, что cumsum () будет работать в этом случае, так как все 3 основных поля (Qty, Buy, Sell) взаимосвязаны.

Ответы [ 3 ]

2 голосов
/ 28 октября 2019

pandas Фреймы данных не предназначены для зацикливания строк. Я предлагаю вам взять на себя тщательное изучение его использования и функций. А пока, это должно помочь вам с тем, что вам нужно (я сделал это на лету, поэтому дайте мне знать, если есть ошибка компиляции):

df['Qty'] = df['Qty'].shift() + df['Buy'].shift() - df['Sell'].shift()
df['Buy'] = df.apply(lambda x: 0 if x['Price'] >= buy_price else min(30 - X['Qty'], 10))
df['Sell'] = df.apply(lambda x: 0 if x['Price'] <= sell_price else min(x['Qty'], 10))
df['Cost'] = df['Buy'] * df['Price']
df['Rev'] = dft['Sell'] * df['Price']
1 голос
/ 28 октября 2019

Более понятным подходом будет написать предикат, который может хранить состояние, а затем вызвать функцию apply один раз. Определите предикат, как показано ниже

class Predicate():
    def __init__(self):
        self.buy_price = 50
        self.sell_price = 100
        self.prev_qty = 0
        self.prev_buy_price = 0
        self.prev_sell_price = 0
    def __call__(self, x):
        x.Qty = self.prev_qty + self.prev_buy_price - self.prev_sell_price
        x.Buy = np.where(x.Price < buy_price, min(30 - x.Qty, 10), 0)
        x.Sell = np.where(x.Price > sell_price, min(x.Qty, 10), 0)
        x.Cost = x.Buy * x.Price
        x.Rev = x.Sell * x.Price
        self.prev_buy_price = x.Buy
        self.prev_qty = x.Qty
        self.prev_sell_price = x.Sell
        return x

И примените предикат как

p = Predicate()
df.apply(p, axis=1)

Дает следующий результат

    Time    Price   Qty Buy Sell    Cost    Rev
0   0.0 44.0    10.0    10.0    0.0 440.0   0.0
1   1.0 100.0   20.0    0.0 0.0 0.0 0.0
2   2.0 40.0    20.0    10.0    0.0 400.0   0.0
3   3.0 110.0   30.0    0.0 10.0    0.0 1100.0
4   4.0 77.0    20.0    0.0 0.0 0.0 0.0
5   5.0 109.0   20.0    0.0 10.0    0.0 1090.0
6   6.0 65.0    10.0    0.0 0.0 0.0 0.0
7   7.0 93.0    10.0    0.0 0.0 0.0 0.0
8   8.0 89.0    10.0    0.0 0.0 0.0 0.0
9   9.0 73.0    10.0    0.0 0.0 0.0 0.0
1 голос
/ 28 октября 2019

Использование cumsum и np.where вместо apply:

df["Buy"]= np.where(df["Price"]<50, np.where((30 - df["Qty"]) > 10, 10, 30 - df["Qty"]), 0)
df["Sell"] = np.where(df["Price"]>100, np.where(df["Qty"] > 10, df["Qty"], 10), 0)
df["Qty"] = (df["Buy"].shift()-df["Sell"].shift()).cumsum()
df['Cost'] = df['Buy'] * df['Price']
df['Rev'] = df['Sell'] * df['Price']

print (df)
#
   Time  Price   Qty   Buy  Sell   Cost     Rev
0     0     44   NaN  10.0   0.0  440.0     0.0
1     1    100  10.0   0.0   0.0    0.0     0.0
2     2     40  10.0  10.0   0.0  400.0     0.0
3     3    110  20.0   0.0  10.0    0.0  1100.0
4     4     77  10.0   0.0   0.0    0.0     0.0
5     5    109  10.0   0.0  10.0    0.0  1090.0
6     6     65   0.0   0.0   0.0    0.0     0.0
7     7     93   0.0   0.0   0.0    0.0     0.0
8     8     89   0.0   0.0   0.0    0.0     0.0
9     9     73   0.0   0.0   0.0    0.0     0.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...