基于其他列中的值为多个dataframe列设置上限

2024-05-23 22:58:31 发布

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

这是我在StackOverflow的第一篇帖子,希望我不会打破任何发帖惯例

我有一个包含账户ID、当前余额、信用额度和每月EADs的数据框架。 Example Table

import pandas as pd
df = pd.DataFrame({'Acct_ID': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 
                   'Current_Balance': [8000, 7000, 6000, 8000, 7000, 6000, 3000, 2000, 5000, 5000],
                   'Credit_Limit': [10000, 9000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1000],
                   'EAD_1': [8500, 7500, 6500, 8500, 7500, 6500, 5500, 4500, 3500, 500],
                   'EAD_2': [9500, 8500, 7500, 6500, 5500, 4500, 3500, 2500, 1500, 1500],
                   'EAD_3': [10500, 9500, 8500, 7500, 6500, 5500, 4500, 3500, 2500, 2000],
                   'EAD_4': [12000, 11000, 10000, 9000, 8000, 7000, 6000, 5000, 4000, 3000]})

我需要对使用以下逻辑的EAD列应用cap:

如果当前余额超过信用额度,则每次观察的每月EAD为EAD和当前余额中的较小者。或者,如果当前余额未超过信用额度,则每次观察的每月EAD为EAD和信用额度中的较小者。每月EADs也适用0的下限

我的背景是SAS,我最近才开始使用Python,因此很难找到有效的解决方案。我在下面列出了用于概述逻辑的SAS等效值,仅供参考:

if Current_Balance > Credit_limit then do;
    EAD_&j. = Max(Min(EAD_&j.,Current_Balance),0);
end;

else do;
    EAD_&j. = Max(Min(EAD_&j.,Credit_limit),0); 
end;

我已经有了一个Python的工作解决方案,但运行起来需要很长时间。我目前使用的样本有325k个观察值,我需要对每月EADs的120列应用“封顶”。目前,以下Python代码需要40分钟才能运行。我不敢在1200万条记录的总体上运行此操作…作为比较,使用上面提到的脚本在SAS中执行相同操作需要2-3分钟

def EAD_LT_adjustment(curr_bal, credit_limit, EAD_t):
    if curr_bal > credit_limit:
        return max(min(EAD_t, curr_bal), 0)
    else:
        return max(min(EAD_t, credit_limit), 0)

for k in range(13, lifetime + 1):
    EL_Acc2['EAD_LT_T' + str(k)] = EL_Acc2.apply(lambda x: EAD_LT_adjustment(x['curr_bal'], x['credit_limit'], x['EAD_LT_T' + str(k)]), axis=1)

有没有办法优化代码?目标是在更短的时间内获得相同的结果

多谢各位


Tags: ltidcurrent余额limitbalancecreditsas
1条回答
网友
1楼 · 发布于 2024-05-23 22:58:31

数据帧非常适合于按列操作,这正是规则所需要的。例如,这就是我们如何将您的规则应用于EAD_1,以生成一个新列EAD_1_c

df.loc[df['Current_Balance'] > df['Credit_Limit'],'EAD_1_c'] = df[['EAD_1','Current_Balance']].min(axis=1).clip(0)
df.loc[df['Current_Balance'] <= df['Credit_Limit'],'EAD_1_c'] = df[['EAD_1','Credit_Limit']].min(axis=1).clip(0)

输出:

      Acct_ID    Current_Balance    Credit_Limit    EAD_1    EAD_2    EAD_3    EAD_4    EAD_1_c
       -          -              -     -     -     -      -
 0          1               8000           10000     8500     9500    10500    12000       8500
 1          2               7000            9000     7500     8500     9500    11000       7500
 2          3               6000            8000     6500     7500     8500    10000       6500
 3          4               8000            7000     8500     6500     7500     9000       8000
 4          5               7000            6000     7500     5500     6500     8000       7000
 5          6               6000            5000     6500     4500     5500     7000       6000
 6          7               3000            4000     5500     3500     4500     6000       4000
 7          8               2000            3000     4500     2500     3500     5000       3000
 8          9               5000            2000     3500     1500     2500     4000       3500
 9         10               5000            1000      500     1500     2000     3000        500

您可以像在自己的解决方案中一样循环所有EAD_n。我希望这比你的逐行循环快得多

详见herehere

相关问题 更多 >