【发布时间】:2017-12-11 13:33:40
【问题描述】:
我有一个非常大的数据框,用于一年中每一秒的电池放电时间表。
基本的一系列事件是
- 事件发生
- 电池放电
- 停止放电
- 放电停止X秒后,开始充电
- 电池充满后停止充电
数据框看起来像这样......(原谅我的格式不好)
Index | Freq | Case | Battery OP | Power Required | Battery Energy | SOC | Response timer | Charge Power |
01/01/2016 | 49.5862 | C | Discharging | 300.512 | 1500 | 99.85 | 3 | 0 |
01/01/2016 | 49.5862 | C | Charging | 0 | 1500 | 99.85 | 3 | 1500 |
我目前正在使用 for 循环和一些 if/elseif 语句来遍历每一行,检查电池是否需要充电。
我认为它的效率非常低。我可能内存不足,或者需要几天时间才能完成。
我让它在周末运行,但它仍然没有完成
我确信有更好的方法可以做到这一点,但我不知道。问题是它必须是顺序的。充电状态或电池电量需要根据输入或输出电池的电量以及之前的 SOC%/能量计算每秒的电量。
此处可重现的代码(尽量减少)
import numpy as np
import pandas as pd
Battery_W = 1000
Battery_Wh = 1000/ 3
starting_SOC = 0.75
charge_delay = 5
charging = False
year_test = pd.DataFrame(data = [50.00,50.00,49.99,49.98,49.87,49.76,49.65,49.25,50.00,50.00,50.00,50.00,50.00,50.00,49.99,49.78,49.67,49.46,49.25,49.25,50.00,50.00,50.00,49.95,49.65,49.45,49.65,49.55,50.00,50.00,50.00,50.00,50.00,50.00,50.00,49.95,49.65,49.45,49.65,49.55,49.99,49.68,50.00,50.00,50.00,50.00,50.00,50.00,50.00,50.00],index = range(0,50),columns= ['Freq'])
case_conditions = [
(year_test['Freq'] <= 49.75 ),
(year_test['Freq'] > 49.75 )
]
choices = ['C', 'B']
year_test['Case'] = np.select(case_conditions, choices, default='No Case')
"Battery Operation mode"
op_conditions = [
(year_test['Case'] == 'C'),
(year_test['Case'] == 'B')
]
#%%
op_choices = ['Discharging','Idle']
year_test['Battery OP']= np.select(op_conditions, op_choices, default = 'No OP Mode')
"Calculate power output required"
power_conditions = [
(year_test['Case'] == 'B'),
(year_test['Case'] == 'C')
]
power_choices = [1000,0]
year_test['Power Required']= np.select(power_conditions, power_choices, default = 0)
year_test['Battery Energy'] = 0.0
year_test['SOC%'] = 0
"Response Timer"
year_test['Response timer'] = year_test.groupby('Battery OP').cumcount()
year_test['Response timer'][year_test['Battery OP'] == 'Idle' ] = 0
year_test['Charge Power'] = 0.00
year_test['Battery Energy'] = 0.0
year_test['Battery Energy'].iloc[0] = Battery_Wh * starting_SOC
year_test['Battery Energy'].iloc[0:charge_delay] = Battery_Wh * starting_SOC
for j in range(charge_delay, len(year_test)):
if year_test.iloc[j-(charge_delay) ,3] > 0 and year_test.iloc[j - ((charge_delay) -1), 3] == 0 :
"charge at max rate"
year_test.iloc[j,7] = Battery_W
year_test.iloc[j,2] = "Charging"
charging = True
elif charging == True and year_test.iloc[j-1,4] < starting_SOC * Battery_Wh:
"check if battery charged"
year_test.iloc[j,7] = Battery_W
year_test.iloc[j,2] = "Charging"
elif year_test.iloc[j-1,4] >= starting_SOC * Battery_Wh or charging == False:
charging = False
year_test.iloc[j,7] = 0.0
"New Battery Energy"
year_test.iloc[j,4] = year_test.iloc[(j-1),4] - ((year_test.iloc[j,3])/60/60) + ((year_test.iloc[j,7])/60/60)
if year_test.iloc[j,4] > Battery_Wh :
year_test.iloc[j,4] = Battery_Wh
"Calculate battery SOC% for empty"
year_test['SOC%'] = year_test['Battery Energy'] / Battery_Wh * 100
【问题讨论】:
-
您能否给出一个简化为相关字段和预期输出的示例数据框?阅读您的代码相当困难。
-
我同意 Tillmann 的观点,如果您能提供 mcve,那将很容易为您提供帮助。
-
好的,我现在试试添加一个
-
我认为您可能在代码开头缺少布尔值
charging=True...无论如何,问题显然是在您创建第一列“频率”后追加新列。您有 2 个选项:从字典操作中获取 'Freq' 和 'Case' 列或使用df.itertuples()...让我尝试将其包装在快速代码中... -
你的代码有点不清楚 - 你有什么数据,你想生成什么数据?您能否给出一个示例输入数据框和一个示例输出,以及您期望输出的规则是什么?