根据其他列中的值限制多个数据框列
Capping multiple dataframe columns based on values in other columns
这是我在 Whosebug 中的第一个 post,希望我不会违反任何 posting 约定。
我有一个包含 Acct_ID、Current_Balance、Credit_Limit 和每月 EAD 的数据框。
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 列应用上限:
如果当前余额超过信用额度,则每次观察的每月 EAD 为 EAD 和当前余额中的较小者。或者,如果当前余额不超过信用额度,则每次观察的每月 EAD 是 EAD 和信用额度中的较小者。月度 EAD 也应用了 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 个观察值,我需要将“封顶”应用于每月 EAD 的 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)
有什么优化代码的想法吗? objective 是为了获得相同的结果,但时间明显减少。
谢谢。
DataFrames 非常适合按列操作,这正是您的规则所需要的。例如,这就是我们将您的规则应用到 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
。我希望这比逐行循环快很多
有关详细信息,请参阅 here and here
这是我在 Whosebug 中的第一个 post,希望我不会违反任何 posting 约定。
我有一个包含 Acct_ID、Current_Balance、Credit_Limit 和每月 EAD 的数据框。 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 列应用上限:
如果当前余额超过信用额度,则每次观察的每月 EAD 为 EAD 和当前余额中的较小者。或者,如果当前余额不超过信用额度,则每次观察的每月 EAD 是 EAD 和信用额度中的较小者。月度 EAD 也应用了 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 个观察值,我需要将“封顶”应用于每月 EAD 的 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)
有什么优化代码的想法吗? objective 是为了获得相同的结果,但时间明显减少。
谢谢。
DataFrames 非常适合按列操作,这正是您的规则所需要的。例如,这就是我们将您的规则应用到 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
。我希望这比逐行循环快很多
有关详细信息,请参阅 here and here