曾经违约标记 - 用于信用风险建模 - Python
Ever Default Tagging - for Credit Risk Modelling- Python
我是 python 的新手,在编写这部分代码时遇到了一些困难。因此,为了提供背景知识,我想为信用风险建模做一个永远默认的标记。
0 用于非默认帐户和
默认帐户 1 个
所以 idea/concept 是整个日期性能(12 个月),如果特定客户 (ID) 曾经有过一次违约事件 (1),那么该事件之后的下一次性能(对于那个customer) 将被标记为默认值 (1),即使 'default tagging' 为 0.
所以输入是这样的:
ID
Date Performance
Default Tag
AAA
2021-03-01
0
AAA
2021-04-01
0
AAA
2021-05-01
0
AAA
2021-06-01
0
AAA
2021-07-01
0
AAA
2021-08-01
0
AAA
2021-09-01
0
AAA
2021-10-01
0
AAA
2021-11-01
0
AAA
2021-12-01
0
AAA
2022-01-01
0
AAA
2022-02-01
0
ABB
2021-03-01
0
ABB
2021-04-01
0
ABB
2021-05-01
0
ABB
2021-06-01
1
ABB
2021-07-01
0
ABB
2021-08-01
0
ABB
2021-09-01
1
ABB
2021-10-01
0
ABB
2021-11-01
0
ABB
2021-12-01
0
ABB
2022-01-01
0
ABB
2022-02-01
0
并且输出将出现在这样的新列中:
ID
Date Performance
Ever Default Tag
AAA
2021-03-01
0
AAA
2021-04-01
0
AAA
2021-05-01
0
AAA
2021-06-01
0
AAA
2021-07-01
0
AAA
2021-08-01
0
AAA
2021-09-01
0
AAA
2021-10-01
0
AAA
2021-11-01
0
AAA
2021-12-01
0
AAA
2022-01-01
0
AAA
2022-02-01
0
ABB
2021-03-01
0
ABB
2021-04-01
0
ABB
2021-05-01
0
ABB
2021-06-01
1
ABB
2021-07-01
1
ABB
2021-08-01
1
ABB
2021-09-01
1
ABB
2021-10-01
1
ABB
2021-11-01
1
ABB
2021-12-01
1
ABB
2022-01-01
1
ABB
2022-02-01
1
请试试这个:
df = df.reset_index(drop=True)
for id in df['ID'].unique():
try:
df.loc[df['ID']==id,['Ever Default Tag']] = 0
index_value = list(df[(df['ID']==id)&(df['Default Tag']==1)].index)[0]
df.loc[index_value:,['Ever Default Tag']] = 1
except:
continue
df['Ever Default Tag'] = df['Ever Default Tag'].astype(int)
这里有一些代码可以完成您的问题:
(UPDATED 将 one-line lambda 替换为 apply
更具可读性的函数,并更正默认时的 off-by-one 错误开始。)
import pandas as pd
records = [
{'ID':'AAA', 'Date Performance': '2021-03-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-04-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-05-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-06-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-07-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-08-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-09-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-10-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-11-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-12-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2022-01-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2022-02-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-03-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-04-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-05-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-06-01', 'Default Tag': 1},
{'ID':'AAB', 'Date Performance': '2021-07-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-08-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-09-01', 'Default Tag': 1},
{'ID':'AAB', 'Date Performance': '2021-10-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-11-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-12-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2022-01-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2022-02-01', 'Default Tag': 0}
]
df = pd.DataFrame(records)
def hasEverDefaulted(df, x):
id, dt = 'ID', 'Date Performance'
hasSameIdAndNotLaterDate = (df[id] == x[id]) & (df[dt] <= x[dt])
return int(sum(df[hasSameIdAndNotLaterDate]['Default Tag']) > 0)
df['Default Tag'] = df.apply(lambda x: hasEverDefaulted(df, x), axis=1)
df.rename(columns={'Default Tag': 'Ever Default Tag'}, inplace=True)
print(df)
输出:
ID Date Performance Ever Default Tag
0 AAA 2021-03-01 0
1 AAA 2021-04-01 0
2 AAA 2021-05-01 0
3 AAA 2021-06-01 0
4 AAA 2021-07-01 0
5 AAA 2021-08-01 0
6 AAA 2021-09-01 0
7 AAA 2021-10-01 0
8 AAA 2021-11-01 0
9 AAA 2021-12-01 0
10 AAA 2022-01-01 0
11 AAA 2022-02-01 0
12 AAB 2021-03-01 0
13 AAB 2021-04-01 0
14 AAB 2021-05-01 0
15 AAB 2021-06-01 1
16 AAB 2021-07-01 1
17 AAB 2021-08-01 1
18 AAB 2021-09-01 1
19 AAB 2021-10-01 1
20 AAB 2021-11-01 1
21 AAB 2021-12-01 1
22 AAB 2022-01-01 1
23 AAB 2022-02-01 1
更新#2:
以下是对 apply()
.
的调用所发生情况的解释
当您使用参数 axis=1
调用 pandas 中类型 DataFrame
的对象的 apply()
方法时,它会为每一行重复调用指定的函数DataFrame
对象和 Series
对象,该对象包含给定行的 DataFrame
对象的列中的值。
在此答案的代码中,被调用的函数是一个 lambda
,以给定的行作为参数 x
,它又以参数 [=23] 调用 hasEverDefaulted()
=] 和 x
.
在 hasEverDefaulted()
中,我们进行矢量化逻辑计算以获得一列 boolean
值,该列扫描 df
的整个 'ID'
列,检查是否与'ID'
行 x
中的值,并扫描整个 'Date Performance'
列检查 <=
行 x
中的日期值的日期值。然后,我们使用矢量化逻辑“与”运算符 &
将这些和 select(通过将对应于 x
的结果行设置为 True
)仅与当前匹配的值组合行的“id”并且还有一个不晚于当前行的“日期”。我们将此矢量化(柱状)结果分配给变量 hasSameIdAndNotLaterDate
.
然后,我们将此变量用作 boolean
过滤器,从 df
仅 True
行到 select,然后我们对 Default Tag
求和这些行的列值,通过测试此总和来创建一个 boolean
值,以检查它是否为 > 0
(在这种情况下,该行的 'ID'
在该行的 [=31 上或之前出现默认值=]) 和 return 此 boolean
值的 int
版本(即 0
或 1
)。
在调用 apply()
的语句中,我们将 apply()
的列式结果分配给 df
的 'Default Tag'
列。为了清楚地表明我们现在已经更改了此列的语义(现在指示默认是否发生在每行的 'Date Performance'
日期或之前),我们调用 [=15] 的 rename()
方法=] object df
将列名称更改为 'Ever Default Tag'
.
我是 python 的新手,在编写这部分代码时遇到了一些困难。因此,为了提供背景知识,我想为信用风险建模做一个永远默认的标记。
0 用于非默认帐户和 默认帐户 1 个
所以 idea/concept 是整个日期性能(12 个月),如果特定客户 (ID) 曾经有过一次违约事件 (1),那么该事件之后的下一次性能(对于那个customer) 将被标记为默认值 (1),即使 'default tagging' 为 0.
所以输入是这样的:
ID | Date Performance | Default Tag |
---|---|---|
AAA | 2021-03-01 | 0 |
AAA | 2021-04-01 | 0 |
AAA | 2021-05-01 | 0 |
AAA | 2021-06-01 | 0 |
AAA | 2021-07-01 | 0 |
AAA | 2021-08-01 | 0 |
AAA | 2021-09-01 | 0 |
AAA | 2021-10-01 | 0 |
AAA | 2021-11-01 | 0 |
AAA | 2021-12-01 | 0 |
AAA | 2022-01-01 | 0 |
AAA | 2022-02-01 | 0 |
ABB | 2021-03-01 | 0 |
ABB | 2021-04-01 | 0 |
ABB | 2021-05-01 | 0 |
ABB | 2021-06-01 | 1 |
ABB | 2021-07-01 | 0 |
ABB | 2021-08-01 | 0 |
ABB | 2021-09-01 | 1 |
ABB | 2021-10-01 | 0 |
ABB | 2021-11-01 | 0 |
ABB | 2021-12-01 | 0 |
ABB | 2022-01-01 | 0 |
ABB | 2022-02-01 | 0 |
并且输出将出现在这样的新列中:
ID | Date Performance | Ever Default Tag |
---|---|---|
AAA | 2021-03-01 | 0 |
AAA | 2021-04-01 | 0 |
AAA | 2021-05-01 | 0 |
AAA | 2021-06-01 | 0 |
AAA | 2021-07-01 | 0 |
AAA | 2021-08-01 | 0 |
AAA | 2021-09-01 | 0 |
AAA | 2021-10-01 | 0 |
AAA | 2021-11-01 | 0 |
AAA | 2021-12-01 | 0 |
AAA | 2022-01-01 | 0 |
AAA | 2022-02-01 | 0 |
ABB | 2021-03-01 | 0 |
ABB | 2021-04-01 | 0 |
ABB | 2021-05-01 | 0 |
ABB | 2021-06-01 | 1 |
ABB | 2021-07-01 | 1 |
ABB | 2021-08-01 | 1 |
ABB | 2021-09-01 | 1 |
ABB | 2021-10-01 | 1 |
ABB | 2021-11-01 | 1 |
ABB | 2021-12-01 | 1 |
ABB | 2022-01-01 | 1 |
ABB | 2022-02-01 | 1 |
请试试这个:
df = df.reset_index(drop=True)
for id in df['ID'].unique():
try:
df.loc[df['ID']==id,['Ever Default Tag']] = 0
index_value = list(df[(df['ID']==id)&(df['Default Tag']==1)].index)[0]
df.loc[index_value:,['Ever Default Tag']] = 1
except:
continue
df['Ever Default Tag'] = df['Ever Default Tag'].astype(int)
这里有一些代码可以完成您的问题:
(UPDATED 将 one-line lambda 替换为 apply
更具可读性的函数,并更正默认时的 off-by-one 错误开始。)
import pandas as pd
records = [
{'ID':'AAA', 'Date Performance': '2021-03-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-04-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-05-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-06-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-07-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-08-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-09-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-10-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-11-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2021-12-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2022-01-01', 'Default Tag': 0},
{'ID':'AAA', 'Date Performance': '2022-02-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-03-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-04-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-05-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-06-01', 'Default Tag': 1},
{'ID':'AAB', 'Date Performance': '2021-07-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-08-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-09-01', 'Default Tag': 1},
{'ID':'AAB', 'Date Performance': '2021-10-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-11-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2021-12-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2022-01-01', 'Default Tag': 0},
{'ID':'AAB', 'Date Performance': '2022-02-01', 'Default Tag': 0}
]
df = pd.DataFrame(records)
def hasEverDefaulted(df, x):
id, dt = 'ID', 'Date Performance'
hasSameIdAndNotLaterDate = (df[id] == x[id]) & (df[dt] <= x[dt])
return int(sum(df[hasSameIdAndNotLaterDate]['Default Tag']) > 0)
df['Default Tag'] = df.apply(lambda x: hasEverDefaulted(df, x), axis=1)
df.rename(columns={'Default Tag': 'Ever Default Tag'}, inplace=True)
print(df)
输出:
ID Date Performance Ever Default Tag
0 AAA 2021-03-01 0
1 AAA 2021-04-01 0
2 AAA 2021-05-01 0
3 AAA 2021-06-01 0
4 AAA 2021-07-01 0
5 AAA 2021-08-01 0
6 AAA 2021-09-01 0
7 AAA 2021-10-01 0
8 AAA 2021-11-01 0
9 AAA 2021-12-01 0
10 AAA 2022-01-01 0
11 AAA 2022-02-01 0
12 AAB 2021-03-01 0
13 AAB 2021-04-01 0
14 AAB 2021-05-01 0
15 AAB 2021-06-01 1
16 AAB 2021-07-01 1
17 AAB 2021-08-01 1
18 AAB 2021-09-01 1
19 AAB 2021-10-01 1
20 AAB 2021-11-01 1
21 AAB 2021-12-01 1
22 AAB 2022-01-01 1
23 AAB 2022-02-01 1
更新#2:
以下是对 apply()
.
当您使用参数 axis=1
调用 pandas 中类型 DataFrame
的对象的 apply()
方法时,它会为每一行重复调用指定的函数DataFrame
对象和 Series
对象,该对象包含给定行的 DataFrame
对象的列中的值。
在此答案的代码中,被调用的函数是一个 lambda
,以给定的行作为参数 x
,它又以参数 [=23] 调用 hasEverDefaulted()
=] 和 x
.
在 hasEverDefaulted()
中,我们进行矢量化逻辑计算以获得一列 boolean
值,该列扫描 df
的整个 'ID'
列,检查是否与'ID'
行 x
中的值,并扫描整个 'Date Performance'
列检查 <=
行 x
中的日期值的日期值。然后,我们使用矢量化逻辑“与”运算符 &
将这些和 select(通过将对应于 x
的结果行设置为 True
)仅与当前匹配的值组合行的“id”并且还有一个不晚于当前行的“日期”。我们将此矢量化(柱状)结果分配给变量 hasSameIdAndNotLaterDate
.
然后,我们将此变量用作 boolean
过滤器,从 df
仅 True
行到 select,然后我们对 Default Tag
求和这些行的列值,通过测试此总和来创建一个 boolean
值,以检查它是否为 > 0
(在这种情况下,该行的 'ID'
在该行的 [=31 上或之前出现默认值=]) 和 return 此 boolean
值的 int
版本(即 0
或 1
)。
在调用 apply()
的语句中,我们将 apply()
的列式结果分配给 df
的 'Default Tag'
列。为了清楚地表明我们现在已经更改了此列的语义(现在指示默认是否发生在每行的 'Date Performance'
日期或之前),我们调用 [=15] 的 rename()
方法=] object df
将列名称更改为 'Ever Default Tag'
.