[英]Optimize the following section of python code for decaying variables
我在做一個排序的數據集“下面的操作df_pre_decay
包含多個ID的時間序列數據集”,我想我的衰變“ tactic
在不同的速率在每個ID”變量(來自哪里tactic_decay_dict
)。
為衰減的戰術變量' xyz
'創建的變量將與第1個月的戰術變量具有相同的值,而對於所有其他mnth,它將是(((前mnth的衰減的戰術變量' xyz
'的值))相乘(比率)和((當前mnth的戰術變量'tactic'的值)乘以(1-rate))
time_col = 'mnth'
tactic =['overall_details','speaker_total','overall_samples_eu','copay_redemption_count','voucher_redemption_count','dtc']
tactic_decay_dict = dict.fromkeys(tactic,(60,70))
uniq = len(df_pre_decay[time_col].unique())
## Loops for variables and decay rate
for a in tactic_decay_dict:
for b in tactic_decay_dict[a]:
xyz = a+'_s'+str(b)
## Loops for iterating over each row in the dataset
for i in range(len(df_pre_decay)):
df_pre_decay[xyz] = np.where((i%uniq)!=0,
(df_pre_decay[xyz].iloc[i-1])*b/100+
(df_pre_decay[a].iloc[i])*(100-b)/100,
df_pre_decay[a].iloc[i])
我想優化此部分代碼,因為我的數據集中有500萬以上的行花費了30分鍾以上的時間。
編輯:請找到數據集的樣本
ID mnth overall_details speaker_total overall_samples_eu copay_redemption_count voucher_redemption_count dtc
1 201701 3 1 10 9 3 6
1 201702 6 1 0 7 7 10
1 201703 10 8 7 8 9 10
1 201704 3 9 3 0 1 1
1 201705 9 0 8 9 6 4
1 201706 8 3 2 10 8 9
1 201707 3 10 3 0 5 6
1 201708 2 10 3 9 6 2
1 201709 1 3 7 10 8 0
1 201710 3 8 2 8 0 10
1 201711 6 7 4 8 5 6
1 201712 3 8 2 9 4 10
2 201701 7 4 7 4 10 2
2 201702 10 0 2 2 10 5
2 201703 10 6 4 10 5 3
2 201704 4 3 6 4 0 8
2 201705 7 8 9 10 6 10
2 201706 8 0 2 7 1 8
2 201707 10 2 8 1 9 4
2 201708 10 6 7 0 3 5
2 201709 10 10 3 8 9 0
2 201710 2 0 3 5 5 8
2 201711 1 8 0 7 3 4
2 201712 8 5 1 0 7 9
3 201701 2 2 7 7 1 2
3 201702 2 8 10 9 6 9
3 201703 10 5 8 5 9 4
3 201704 6 1 2 4 6 2
3 201705 6 9 4 4 3 0
3 201706 5 1 6 4 1 7
3 201707 0 7 6 9 5 6
3 201708 10 3 2 0 4 5
3 201709 5 8 6 4 10 4
3 201710 8 3 10 6 7 0
3 201711 7 5 6 3 1 10
3 201712 3 9 8 4 10 0
我認為您的代碼無法按預期工作,因為您可以在循環的每一輪中將整個列df_pre_decay[xyz]
有效地設置為單個值。 你(需要或者遍歷數據幀中的每一行for i in range(len(df_pre_decay))
或治療的列向量(如np.where
等numpy的功能一樣),但你是混合了兩者。 向量化方法通常會更快。
對於非矢量化版本,將xyz
列設置為與a
列相同,然后循環遍歷各行,並在需要時設置累加值。
for a in tactic_decay_dict:
for b in tactic_decay_dict[a]:
xyz = a+'_s'+str(b)
## Loops for iterating over each row in the dataset
df_pre_decay[xyz] = df_pre_decay[a]
for i in range(len(df_pre_decay)):
if i % uniq != 0:
df_pre_decay[xyz].iloc[i] = (df_pre_decay[xyz].iloc[i-1] * b/100
+ df_pre_decay[a].iloc[i] * (100 - b)/100)
或替代版本-不確定哪個會更快:
for a in tactic_decay_dict:
for b in tactic_decay_dict[a]:
xyz = a+'_s'+str(b)
column = []
for i, x in enumerate(df_pre_decay[a]):
if i % uniq == 0:
current = x
else:
current = x * b/100 + current * (100-b)/100
column.append(current)
df[xyz] = column
要進行矢量化,您可以使用numpy.ufunc.accumulate
將列分成大塊,並對每個塊應用累積衰減函數。
for a in tactic_decay_dict:
for b in tactic_decay_dict[a]:
xyz = a+'_s'+str(b)
decay_func = np.frompyfunc(lambda u, v: u * b / 100.0 + v * (100-b) / 100.0, 2, 1)
decayed = np.array([])
for top in range(0, len(df_pre_decay), uniq):
chunk = df_pre_decay[a][top:top+uniq]
decayed = np.concatenate((decayed,
decay_func.accumulate(chunk, dtype=np.object).astype(np.float)))
df_pre_decay[xyz] = decayed
一種替代方法是在不同的ID之間插入具有空值的空白行。 然后,您可以將一個累加函數應用於整個列:
# insert blank rows in the data
df.index = df.index + df.index // uniq
df.reindex(index=range(len(df) + len(df) // uniq))
def get_decay_func(b):
def inner(u, v):
if pd.isnull(u) or pd.isnull(v):
return v
else:
return u * b/100.0 + v * (100-b)/100.0
return inner
for a in tactic_decay_dict:
for b in tactic_decay_dict[a]:
decay = get_decay_func(b).accumulate
xyz = a+'_s'+str(b)
df_pre_decay[xyz] = decay(df_pre_decay[a], dtype=np.object).astype(df.float)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.