Python 在熊猫中进行t-1计算的更快方法

Python 在熊猫中进行t-1计算的更快方法,python,python-3.x,pandas,numpy,Python,Python 3.x,Pandas,Numpy,我有一个超过250000行的df。我有几个字段依赖于t-1值。这在excel中很容易做到,但不确定在pandas中最有效的方法是什么。目前,我设置了t[0]值,然后使用for循环来完成其余的工作,但是速度非常慢。有没有更快的方法 非常感谢您的帮助 代码如下 import pandas as pd import numpy as np import math import datetime from scipy.optimize import minimize df = pd.DataFrame

我有一个超过250000行的df。我有几个字段依赖于t-1值。这在excel中很容易做到,但不确定在pandas中最有效的方法是什么。目前,我设置了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个主要领域数量,购买,出售是相互关联的

数据帧不用于在行上循环。我建议你花点时间彻底了解它的用途和功能。同时,这将有助于您完成所需的工作。我是即时完成的,因此,如果出现编译错误,请告诉我:

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']
数据帧不用于在行上循环。我建议你花点时间彻底了解它的用途和功能。同时,这将有助于您完成所需的工作。我是即时完成的,因此,如果出现编译错误,请告诉我:

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']
使用cumsum和np.where代替apply:

使用cumsum和np.where代替apply:


一种更简洁的方法是编写一个可以存储状态的谓词,然后调用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

给出以下结果

    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

一种更简洁的方法是编写一个可以存储状态的谓词,然后调用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

给出以下结果

    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

嗨@abhilb,这是一个神奇的方法!!非常感谢你的帮助。然而,我只有一个问题。t[0]处的值似乎没有对齐,我在函数中添加了一行printx,函数似乎出于某种原因在t[0]上运行了两次,这导致了错误的起点。知道为什么会这样吗?我不知道这个问题。我在文档中看到了以下内容。注意:在当前实现中,apply在第一列/行上调用func两次,以确定它可以采用快速代码路径还是慢速代码路径。如果func有副作用,这可能会导致意外行为,因为它们会对第一列/行生效两次。啊,好的,有道理。我在函数prev_self.Time=x.Time then do…(时间-然后做…)中使用了if语句来解决这个问题,它工作得非常好。比以前快了很多。真的很感激!嗨@abhilb,这是一个神奇的方法!!非常感谢你的帮助。然而,我只有一个问题。t[0]处的值似乎没有对齐,我在函数中添加了一行printx,函数似乎出于某种原因在t[0]上运行了两次,这导致了错误的起点。知道为什么会这样吗?我不知道这个问题。我在文档中看到了以下内容。注意:在当前实现中,apply在第一列/行上调用func两次,以确定它可以采用快速代码路径还是慢速代码路径。如果func有副作用,这可能会导致意外行为,因为它们会对第一列/行生效两次。啊,好的,有道理。我在函数prev_self.Time=x.Time then do…(时间-然后做…)中使用了if语句来解决这个问题,它工作得非常好。比以前快了很多。真的很感激!