两张表如下:
表1:
表2:
需求: 按照表1的“用户唯一ID”,在表2 中找到对应的“客户风险等级”和“评估日期”
难点: 每个“用户唯一ID”对对应不同“评估日期”日期下的“客户风险等级”,所以不能简单的使用pd.merge()
解决方法: 双层循环,找到时间差小的“评估日期”作为当前用户的“客户风险等级”,同时为了体现是最近的信息,必须保证
# 客户风险表
## 因为每个用户在不同时期会有不同的风险等级,所以这里需要一个一个迭代,去匹配与当前交易日期最接近的评估日期下的风险等级
custom_risk = pd.read_csv("./数据表/e.csv", header = 0, names = ["用户唯一ID", "客户风险等级", "评估日期"])
custom_risk["评估日期"] = custom_risk["评估日期"].map(lambda x: "-".join([str(x)[0:4], str(x)[4:6], str(x)[6:]]))
custom_risk["评估日期"] = pd.to_datetime(custom_risk["评估日期"], format = "%Y/%m/%d")
risk_1 = [] # 记录客户风险等级
risk_2 = [] # 记录评估日期
risk_3 = [] # 记录record_miss, 1表示miss
for r in tqdm(range(len(df))):
cur_risk = custom_risk[custom_risk["用户唯一ID"] == df.iloc[r]["用户唯一ID"]]
if(len(cur_risk) == 0):
risk_1.append(float('nan'))
risk_2.append(float('nan'))
risk_3.append(float('nan'))
continue
m = pd.Timedelta(days=100000)
record_correct = -1 # 什么情况是正确的?即:评估时间小于交易日期,且与交易日期最接近
record_miss = 0 # 什么情况是丢失的?即:评估时间大于交易日期,且与交易日期最接近,这个有可能不准,但是也有一定的参考性,
for r1 in range(len(cur_risk)):
if abs(cur_risk.iloc[r1]["评估日期"] - df.iloc[r]["交易日期"]) < m and (cur_risk.iloc[r1]["评估日期"] < df.iloc[r]["交易日期"]):
m = abs(cur_risk.iloc[r1]["评估日期"] - df.iloc[r]["交易日期"])
record_correct = r1
if record_correct == -1: # 说明当前的交易日期之前,没有进行风险评估
m = pd.Timedelta(days=100000)
for r1 in range(len(cur_risk)):
if abs(cur_risk.iloc[r1]["评估日期"] - df.iloc[r]["交易日期"]) < m:
m = abs(cur_risk.iloc[r1]["评估日期"] - df.iloc[r]["交易日期"])
record_miss = r1
risk_1.append(cur_risk.iloc[record_miss]["客户风险等级"])
risk_2.append(cur_risk.iloc[record_miss]["评估日期"])
risk_3.append(1)
else:
risk_1.append(cur_risk.iloc[record_correct]["客户风险等级"])
risk_2.append(cur_risk.iloc[record_correct]["评估日期"])
risk_3.append(0)
df["客户风险等级"] = risk_1
df["客户风险等级_评估日期"] = risk_2
df["客户风险等级_没有被评估"] = risk_3
del risk_1
del risk_2
del risk_3
gc.collect()
就是有点慢,因为数据太多了,200万条,没其他问题。
panda语法:
# 设置一个最小值
m = pd.Timedelta(days=100000)
# pandas的Time直接相减
abs(cur_risk.iloc[r1]["评估日期"] - df.iloc[r]["交易日期"]) < m