通过从sqldb导入的pd Dataframe子集改进性能循环

2024-09-30 12:29:25 发布

您现在位置:Python中文网/ 问答频道 /正文

一般来说,我对python/编码是新手。我花了一段时间才写出下面的代码(很自豪),但现在我遇到了性能问题——不知道如何解决它们

我的任务如下: 每个产品都有一个交货时间和一个生产时间戳。生产时间可从交货前1天15:00到交货前30分钟。我想为每个交付小时将生产时间聚合为15分钟的间隔,并在每个间隔内为生产单元执行几个简单的操作 (并非所有功能都是内置的) -成交量加权平均价格、总数量(总和)、标准差等

我的问题是: 这个数据集由大约1100万个数据点组成。计算6个月的数值花了我24个多小时。我尝试在sql查询中循环,只导入了15分钟的句点,但情况更糟

我的问题是: 你认为有什么办法可以提高这次行动的效果吗? 这将是惊人的<;三


原始输入数据看起来像í学生:

Column StartOfDelivery EndOfDelivery ProductionDateTime PriceEURpMW QuantityMW p*Q 73 2017-01-03 01:00:00 2017-01-03 02:00:00 2017-01-02 19:03:00 37,4 20 748 80 2017-01-03 01:00:00 2017-01-03 02:00:00 2017-01-02 19:08:00 35,9 25 897,5 86 2017-01-03 01:00:00 2017-01-03 02:00:00 2017-01-02 19:23:00 36,3 1 36,3 94 2017-01-03 01:00:00 2017-01-03 02:00:00 2017-01-02 19:24:00 35,3 0,4 14,12 915 2017-01-03 02:00:00 2017-01-03 03:00:00 2017-01-02 23:47:00 33,7 5 168,5 929 2017-01-03 02:00:00 2017-01-03 03:00:00 2017-01-02 23:50:00 32,6 0,3 9,78 340 03.01.2017 02:00:00 2017-01-03 03:00:00 2017-01-02 22:17:00 34 7,9 268,6 345 2017-01-03 02:00:00 2017-01-03 03:00:00 2017-01-02 22:19:00 34 0,8 27,2


输出数据如下所示:

index   StartDelivery   Production(intervall)   Quantity    VWAP
17  2017-01-03 01:00:00 2017-01-02 19:00:00       45       36,56666667
18  2017-01-03 01:00:00 2017-01-02 19:15:00       1,4      36,01428571
...
69  2017-01-03 02:00:00 2017-01-02 22:15:00       8,7      34
70  2017-01-03 02:00:00 2017-01-02 23:45:00       5,3      33,63773585

到目前为止我的代码是:

import mysql.connector
import numpy as np
import pandas as pd
import datetime




conn=mysql.connector.connect(user='AriHeck',password='none',host='local',database='DataEvaluation', port=3308)
df = pd.read_sql("select StartOfDelivery,EndOfDelivery,ProdDateTime,PriceEURpMW,QuantityMW, PriceEURpMW*QuantityMW as 'p*Q'  from `Production`\
where timestampdiff(hour,StartOfDelivery,EndOfDelivery)=1 AND StartOfDelivery >= '2017-01-03 01:00:00'  AND StartOfDelivery < '2017-01-03 03:00:00'", con=conn)

#Delivery Time Loop
dt=datetime.datetime.strptime('2017-01-03 01:00:00', "%Y-%m-%d %H:%M:%S") 
end_date=datetime.datetime.strptime('2017-01-05 00:00:00', "%Y-%m-%d %H:%M:%S")

#Dummies loops
incr_delivery_loop=datetime.timedelta(hours=1)
incr_production_loop=datetime.timedelta(minutes=15)
delta_start=datetime.timedelta(days=1) 
delta_end=datetime.timedelta(minutes=30)

#Dummies Data
a=1
delivery_array=[0]*a
production_array=[0]*a
time_remaining_array=[0]*a
VWAP_array=np.zeros(a)
quantity_array=np.zeros(a)

#Start Delivery time loop
while (dt <= end_date):

    #Production Time Loop: 
        #Start Production: 1 Day before delivery 15:00 (3:00 PM), End Production 30 mins before delivery
    prod_time=(dt-delta_start).replace(hour=15)
    end_prod=dt-delta_end 

    while (prod_time<=end_prod):

        quantity=df[(df['StartOfDelivery']==dt)& (df['ProdDateTime']>=prod_time) & (df['ProdDateTime']<(prod_time+incr_production_loop))].QuantityMW.sum()
        if (quantity==0):
            VWAP=0        
        else:   
            #Calculate  Volume Weighted Average Price
            pq_total=df[(df['StartOfDelivery']==dt)& (df['ProdDateTime']>=prod_time) & (df['ProdDateTime']<(prod_time+incr_production_loop))]['p*Q'].sum()
            VWAP=pq_total/quantity

        #Save values to  arrays
        VWAP_array=np.append(VWAP_array,VWAP)
        quantity_array=np.append(quantity_array,quantity)
        delivery_array.append(dt)
        production_array.append(prod_time)

       #Increments
        prod_time=prod_time+incr_production_loop

    dt=dt+incr_delivery_loop
#END LOOPS

#Save to Dataframe 
WAP_dict={'TimeOfDelivery':delivery_array,
          'ProductionDateTime':production_array,
          'VWAP':VWAP_array,
          'Quantity':quantity_array,} 
df_WAP=pd.DataFrame(WAP_dict)
df_WAP=df_WAP[['TimeOfDelivery','ProductionDateTime','Quantity','VWAP']]


#Output
print(df_WAP.head(50)) 

python 3.4、Windows 10、eclipse IDE


Tags: loopdfdatetimetimedtprodarrayquantity
1条回答
网友
1楼 · 发布于 2024-09-30 12:29:25

欢迎来到pythonProfiling您的代码将是一个很好的起点:)

也就是说,随着数据集的增长,每次调用:

df['some_column']==some_variable

越来越贵了。如果您在处理2天的数据时表现良好,但在扩展到6个月时表现下降,则可能是罪魁祸首

尝试通过在SQL查询的末尾添加order by StartOfDelivery对数据进行预排序。然后将数据帧拆分为一个数据帧列表,其中每个子帧只包含循环体内部所需的15分钟增量的记录

然后可以将该列表作为主循环进行迭代,而不是:

while (dt <= end_date):

这将删除所有的数据帧过滤,并使执行时间与数据集大小成线性(ish)

相关问题 更多 >

    热门问题