如何使这个循环更有效?

时间:2015-08-01 17:15:13

标签: python performance pandas

我有大约50万笔贷款的历史收集,其中一些已经违约,有些则没有。我的数据框是lcd_temp。如果贷款违约(lcd_temp),年贷款利率(loan_amnt),贷款期限Total Defaults,则clean_rate有贷款额度(clean_term)的信息。 1}}),从发起到默认的几个月(mos_to_default)。如果没有默认值,则mos_to_default等于clean_term

我想计算每笔贷款的累积现金流[cum_cf],作为默认情况下支付的所有优惠券的总和加上(1严重性)贷款违约,如果是loan_amnt按时还钱。

这是我的代码,需要花费很长时间才能运行:

severity = 1

for i in range (0,len(lcd_temp['Total_Defaults'])-1):
    if (lcd_temp.loc[i,'Total_Defaults'] ==1):
    # Default, pay coupon only until time of default, plus (1-severity)
        lcd_temp.loc[i,'cum_cf'] = ((lcd_temp.loc[i,'mos_to_default'] /12)  * lcd_temp.loc[i,'clean_rate'])+(1 severity)*lcd_temp.loc[i,'loan_amnt']
    else: 
    # Total cf is sum of coupons (non compounded) + principal 
        lcd_temp.loc[i,'cum_cf'] = (1+lcd_temp.loc[i,'clean_term']/12* lcd_temp.loc[i,'clean_rate'])*lcd_temp.loc[i,'loan_amnt']

欢迎任何有关提高速度(至少需要一个小时)的想法或建议!

1 个答案:

答案 0 :(得分:5)

假设您正在使用Pandas / NumPy,替换if-then构造(例如您正在使用的构造)的标准方法是使用np.where(mask, A, B)mask是一个布尔值数组。如果为True,则返回A的相应值。如果为False,则返回B的相应值。结果是一个与mask形状相同的数组,其值为A和/或B

severity = 1

mask = (lcd_temp['Total_Defaults'] == 1)
A = (((lcd_temp['mos_to_default'] /12) * lcd_temp['clean_rate'])
     + (1 severity)*lcd_temp['loan_amnt'])
B = (1+lcd_temp['clean_term']/12 * lcd_temp['clean_rate'])*lcd_temp['loan_amnt']

lcd_temp['cum_cf'] = np.where(mask, A, B)

请注意,这会对整列而不是逐行执行计算。这大大提高了性能,因为它为Pandas / NumPy提供了将更大的值数组传递给快速底层C / Fortran函数的机会(在这种情况下,执行算术)。当你逐行工作时,你在Python循环中执行标量算术,这使得NumPy没有机会闪耀。 如果你必须逐行计算,那么使用普通的Python就可以了(也许更好)。

即使AB计算整个列的值 - 并且某些值未在np.where返回的最终结果中使用 - 这仍然比计算更快假设行数超过一定数量,逐行排列。