creditCardIndexParser.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. #从“贷记卡信息”中提取,人民币账户、状态不为呆账、未激活、销户,授信额度:SUM(各账户授信额度),
  2. # 如同一个机构有多个账户,只取额度最高的计算
  3. import numpy as np;#
  4. import pandas as pd
  5. import utils
  6. import math;
  7. import log
  8. logger = log.logger
  9. #使用中贷记卡平均发卡天数
  10. #三寿
  11. def getAvgUseCreditCardDay(creditDf,creditCardDfZ,reportTime):
  12. activeDf = creditDf[(creditDf['币种'] == '人民币元') & (creditDf['账户状态'] == '正常')];
  13. activeDfZ = creditCardDfZ[(creditCardDfZ['币种'] == '人民币元') & (creditCardDfZ['账户状态'] == '正常')];
  14. openDateDf = activeDf["开立日期"]
  15. if not activeDfZ.empty:
  16. openDateDf.append(activeDfZ["开立日期"])
  17. if not openDateDf.empty:
  18. result= math.ceil(np.mean(openDateDf.apply(lambda x: utils.difDateReportTime(reportTime,x ))))
  19. else:
  20. result= None
  21. return result
  22. #额度使用 >= 50 % 的贷记卡数
  23. def getUseRateCount(creditCardDf,creditCardDfZ,rate):
  24. creditCardDf = creditCardDf[creditCardDf['账户授信额度'] > 0]
  25. creditCardDf = creditCardDf[creditCardDf['已用额度'] / creditCardDf['账户授信额度'] >= rate]
  26. creditCardDfZ = creditCardDfZ[creditCardDfZ['账户授信额度'] > 0]
  27. creditCardDfZ = creditCardDfZ[creditCardDfZ['透支余额'] / creditCardDfZ['账户授信额度'] >= rate]
  28. return creditCardDf.index.size+creditCardDfZ.index.size
  29. #开户1年以内历史逾期90+贷记卡和准贷记卡数
  30. def getOverDueCount(creditCardDf,creditCardPayRecordMergeDf,reportTime,overValue,month):
  31. openAccountDfTmp = creditCardDf[creditCardDf['开立日期'] > utils.getLastMonthDate(reportTime, month)]
  32. overdueCreditPayRcdDfTmp = creditCardPayRecordMergeDf[
  33. creditCardPayRecordMergeDf['账户编号'].isin(openAccountDfTmp['账户编号'].values)]
  34. overdueCreditPayRcdDfTmp = utils.replacePayRcdStatusOverdue(overdueCreditPayRcdDfTmp)
  35. overdueCreditPayRcdDfTmp = overdueCreditPayRcdDfTmp[overdueCreditPayRcdDfTmp['还款状态'] >= overValue]
  36. return overdueCreditPayRcdDfTmp.index.size
  37. #最大信用账户天数(贷款&贷记卡人民账户)
  38. def getMaxAmtAccountDay(loanDf,creditDf,creditCardDfZ,reportTime):
  39. activeDf = creditDf[(creditDf['币种'] == '人民币元')].reset_index(drop=True);
  40. activeDfZ = creditCardDfZ[(creditCardDfZ['币种'] == '人民币元')].reset_index(drop=True);
  41. maxLoanAmt = np.max(loanDf["借款金额(本金)"])
  42. maxCreditAmt = np.max(activeDf["账户授信额度"])
  43. maxCreditAmtZ = np.max(activeDfZ["账户授信额度"])
  44. openDate = ""
  45. if str(maxLoanAmt)!="nan" and str(maxCreditAmt)!="nan":
  46. if maxLoanAmt>=maxCreditAmt:
  47. maxDateIndex = np.argmax(loanDf["借款金额(本金)"])
  48. openDate = loanDf.loc[maxDateIndex, :].dropna()[3]
  49. elif maxLoanAmt<maxCreditAmt:
  50. maxDateIndex = np.argmax(activeDf["账户授信额度"])
  51. openDate = activeDf.loc[maxDateIndex, :].dropna()[3]
  52. elif str(maxLoanAmt)!="nan" and str(maxCreditAmt)=="nan":
  53. maxDateIndex = np.argmax(loanDf["借款金额(本金)"])
  54. openDate = loanDf.loc[maxDateIndex, :].dropna()[3]
  55. elif str(maxLoanAmt) == "nan" and str(maxCreditAmt) != "nan":
  56. maxDateIndex = np.argmax(activeDf["账户授信额度"])
  57. openDate = activeDf.loc[maxDateIndex, :].dropna()[3]
  58. elif str(maxCreditAmt) == "nan" and str(maxCreditAmtZ) != "nan":
  59. maxDateIndex = np.argmax(maxCreditAmtZ["账户授信额度"])
  60. openDate = maxCreditAmtZ.loc[maxDateIndex, :].dropna()[3]
  61. if openDate !="":
  62. return utils.difDateReportTime(reportTime,openDate)
  63. else:
  64. logger.error(str(maxLoanAmt)+"#"+str(maxCreditAmt)+str(maxCreditAmtZ))
  65. return None
  66. #最大授信额度
  67. def getMaxCreditAmt(creditDf):
  68. creditDf = creditDf.sort_values(by=["发卡机构", "账户授信额度"], ascending=(True, False))
  69. creditDf = creditDf.groupby(['发卡机构']).head(1)
  70. maxCreditAmt = np.sum(creditDf['账户授信额度'])
  71. return maxCreditAmt
  72. #最近新发放的3张贷记卡平均额度
  73. def getAvgCreditAmt(creditDf):
  74. creditDf = creditDf.sort_values(by=["开立日期"], ascending=(False))
  75. creditDf = creditDf.head(3)
  76. avgCreditAmt = np.mean(creditDf['账户授信额度'])
  77. return round(avgCreditAmt,2)
  78. #从“贷记卡信息”中提取,人民币账户、状态不为呆账、未激活、销户,统计(已用额度/授信额度>=100%的机构数)/总机构数
  79. # 机构数为去重后的机构代码的数量
  80. def getUseRate(creditDf,df,rate):
  81. # creditDf = creditDf.sort_values(by=["开立日期"], ascending=(False))
  82. # creditDf = creditDf.head(3)
  83. # avgCreditAmt = np.mean(creditDf['账户授信额度'])
  84. creditDf = creditDf[creditDf['账户授信额度']>0]
  85. creditDf = creditDf[creditDf['已用额度']/creditDf['账户授信额度']>=rate]
  86. if df['发卡机构'].unique().size>0:
  87. return round(creditDf['发卡机构'].unique().size / df['发卡机构'].unique().size,3)
  88. else:
  89. return None
  90. # 从“贷款信息”中提取,剔除“账户状态”为结清、转出、呆账、呆帐后,各笔贷款按转换为数字后的“24个月(账户)还款状态”的后3位数字中,取最大值即为该账户的近3月最大逾期期数数,然后max(每个账户的近3月最大逾期数)
  91. # 例如记录1最后3位数为136,记录2最后3位数为135;则近3月最大逾期期数数=6
  92. # “24个月(账户)还款状态”
  93. # 还款记录按日期排序最近3笔的最大逾期期数
  94. def getPayRcdMaxOverdueNum(payRcdDf,month):
  95. # dateStr = utils.getLastMonthDate("",month)
  96. payRcdDf = payRcdDf.sort_values(by=["账户编号","还款日期"] , ascending=(True,False))
  97. payRcdDf = payRcdDf.groupby(['账户编号']).head(month)
  98. payRcdDf = payRcdDf[payRcdDf['还款状态']>0]
  99. # maxOverdueNum = np.max(payRcdDf['还款状态'])
  100. payRcdTimesDf = payRcdDf.groupby('账户编号', as_index=False)['账户编号'].agg({'次数': 'count'})
  101. maxOverdueNum = np.max(payRcdTimesDf['次数'])
  102. return maxOverdueNum;
  103. # 当前一共透支期数
  104. # SUM(所有准贷记卡账户当前透支期数),单账户透支期数根据还款记录里当期账户状态,if 为 ("/","*","C","N","#","M") 转化为 "0";if 为("G") 转化为 "7";if为("B")转化为"7";if 为("D") 转化为 "1"。
  105. def getCurOverdueNum(payRcdDf):
  106. # dateStr = utils.getLastMonthDate("",month)
  107. payRcdDf = payRcdDf.sort_values(by=["账户编号","还款日期"] , ascending=(True,False))
  108. payRcdDf = payRcdDf.groupby(['账户编号']).head(1)
  109. # payRcdDf = payRcdDf[payRcdDf['还款状态']>0]
  110. overdueSum = np.sum(payRcdDf['还款状态'])
  111. return overdueSum;
  112. ## 从“信贷交易信息明细”中“非循环贷账户”、“循环额度下分账户”、“循环贷账户”提取,剔除状态为结清、
  113. # 转出、呆账,MAX(各账户24月内发生逾期的次数),逾期符号判断;数字1234567,字母"G"、"D"、"B"。
  114. # 统计存在最大逾期期数账户开立日期距报告日期月数,若存在多笔账户,选择开立日期距报告日期最近的。
  115. def getPayRcdMaxOverdueNumMonth(payRcdDf,df,reportTime,month):
  116. # if not df.empty:
  117. # # payRcdDf = payRcdDf.sort_values(by=["账户编号","还款日期"] , ascending=(True,False))
  118. # # payRcdDf = payRcdDf.groupby(['账户编号']).head(month)#先取出近两年
  119. # # payRcdDf = payRcdDf.sort_values(by=["账户编号", "还款状态"], ascending=(True, False))
  120. # # payRcdDf = payRcdDf.groupby(['账户编号']).head(1)#取各个账号的最大值
  121. # # endDateDf = df[["账户编号", "截至日期月份"]];
  122. # # # payRcdDf = payRcdDf.set_index('账户编号')
  123. # # endDateDf = endDateDf.set_index('账户编号')
  124. # # payRcdDf = payRcdDf.join(endDateDf,on='账户编号')
  125. # # maxOverdueNum = None;
  126. # # if not payRcdDf.empty:
  127. # # if np.max(payRcdDf['还款状态'])!=0:#没有逾期不要与报告器计算
  128. # # maxOverdueNum = int(np.max(payRcdDf['还款状态'] + payRcdDf['截至日期月份']))
  129. # # return maxOverdueNum;
  130. # # else:
  131. # # return None;
  132. # # return None;
  133. if not df.empty:
  134. payRcdDf = payRcdDf.sort_values(by=["账户编号", "还款日期"], ascending=(True, False))
  135. payRcdDf = payRcdDf.groupby(['账户编号']).head(month)
  136. payRcdDf = payRcdDf[payRcdDf['还款状态'] > 0]
  137. # maxOverdueNum = np.max(payRcdDf['还款状态'])
  138. payRcdTimesDf = payRcdDf.groupby('账户编号', as_index=False)['账户编号'].agg({'次数': 'count'})
  139. if not payRcdTimesDf.empty:
  140. maxOverdueNumIndex = np.argmax(payRcdTimesDf['次数'])
  141. row = payRcdTimesDf.loc[maxOverdueNumIndex, :]
  142. accountNum = row[0]
  143. openDate = df[df['账户编号'] == (accountNum)].reset_index(drop=True).loc[0,'开立日期']
  144. return utils.difMonthReportTime(openDate, reportTime);
  145. return None;
  146. #近3月开卡最高额度
  147. def getLastMonthMaxCreditAmt(creditDf,reportTime,month):
  148. creditDf = creditDf[creditDf['开立日期'] >= utils.getLastMonthDate(reportTime,month)]
  149. # creditDf = creditDf.sort_values(by=["发卡机构", "账户授信额度"], ascending=(True, False))
  150. # creditDf = creditDf.groupby(['发卡机构']).head(1)
  151. maxCreditAmt = np.max(creditDf['账户授信额度'])
  152. return maxCreditAmt
  153. #近3月开卡最低额度
  154. def getLastMonthMinCreditAmt(creditDf,reportTime,month):
  155. creditDf = creditDf[creditDf['开立日期'] >= utils.getLastMonthDate(reportTime,month)]
  156. maxCreditAmt = np.min(creditDf['账户授信额度'])
  157. return maxCreditAmt
  158. #近3月开卡平均额度
  159. def getLastMonthAvgCreditAmt(creditDf,reportTime,month):
  160. creditDf = creditDf[creditDf['开立日期'] >= utils.getLastMonthDate(reportTime,month)]
  161. maxCreditAmt = np.mean(creditDf['账户授信额度'])
  162. return round(maxCreditAmt,2)
  163. #贷款最近一次还款日期距今时长
  164. #从“贷款信息”中提取,取客户的正常还款行为,不取因为某种特定的行为而产生的还款,
  165. # 剔除转出、结清、呆账、呆帐后,取各贷款记录的“最近一次还款日期”的最小值,然后计算距离报告时间的天数,MIN(day(报告时间-最近一次还款日期))
  166. def getLastPayDateMinDays(df,reportTime):
  167. return utils.difDateReportTime(reportTime,np.max(df['最近一次还款日期']))
  168. #连续计算算法
  169. def calcContinuos(x):
  170. max=0
  171. tmp=0
  172. for a in x:
  173. if int(a)>=1 :
  174. tmp=tmp+1
  175. else:
  176. if tmp>max:
  177. max=tmp
  178. tmp=0
  179. if max<tmp:
  180. max=tmp
  181. return max
  182. #获取最大连续逾期月份数
  183. def getContinuousOverdueMonth(payRcdDf,df,month):
  184. payRcdDf = payRcdDf.sort_values(by=["账户编号", "还款日期"], ascending=(True, False))
  185. payRcdDf = payRcdDf.groupby(['账户编号']).head(month)
  186. accountNoDf = payRcdDf['账户编号'].unique()
  187. maxContinuousAr = []
  188. for no in accountNoDf:
  189. payRcdTmp = payRcdDf[payRcdDf['账户编号'].isin([no])]
  190. result = payRcdTmp['还款状态'].rolling(month).apply(calcContinuos).max()
  191. if str(result)!="nan":
  192. maxContinuousAr.append(result)
  193. # if str(np.max(maxContinuousAr))=="nan":
  194. # i=0;
  195. if len(maxContinuousAr)!=0:
  196. return int(np.max(maxContinuousAr))
  197. return None;
  198. #贷款开户数
  199. def getOpenAccount(df,reportTime,month):
  200. if not df.empty:
  201. tmpDf = df
  202. openAccountDf = tmpDf[tmpDf['开立日期'] >= utils.getLastMonthDate(reportTime, month)]
  203. return openAccountDf.index.size
  204. return 0;
  205. # 贷记卡账户近3月逾期期数大于或等于“1”的次数
  206. def getLoanOverdueTimes(payRcdDf, reportTime,times, month):
  207. payRcdDfTmp = payRcdDf.sort_values(by=["账户编号", "还款日期"], ascending=(True, False))
  208. payDate = utils.getLastMonthDate(reportTime,month)
  209. # payRcdDfTmp = payRcdDfTmp[payRcdDfTmp['还款日期']>=payDate]
  210. # 汇算帐20210817
  211. # 改为不包含起始区间的1号,如果报告期为6月,取4,5,6,如果报告期为5月取3,4,5,5月2号 -90天 02-01 不能包含
  212. payRcdDfTmp = payRcdDfTmp[(payRcdDfTmp['还款日期'] > payDate) & (payRcdDfTmp['还款日期'] <= reportTime)] # 1208改为区间,两种逻辑都符合
  213. payRcdDfTmp = utils.replacePayRcdStatusOverdue(payRcdDfTmp)
  214. overdueTimes = payRcdDfTmp[payRcdDfTmp['还款状态']>=times].index.size
  215. return overdueTimes;
  216. # 贷款账户近3月逾期期数大于或等于“1”的金额-汇算帐新增
  217. def getLoanOverdueAmt(payRcdDf, reportTime,times, month):
  218. payRcdDfTmp = payRcdDf.sort_values(by=["账户编号", "还款日期"], ascending=(True, False))
  219. payDate = utils.getLastMonthDate(reportTime,month)
  220. payRcdDfTmp = payRcdDfTmp[(payRcdDfTmp['还款日期'] > payDate)&(payRcdDfTmp['还款日期']<=reportTime)]#1208改为区间,两种逻辑都符合
  221. payRcdDfTmp = utils.replacePayRcdStatusOverdue(payRcdDfTmp)
  222. overdueTimes = payRcdDfTmp[payRcdDfTmp['还款状态']>=times]
  223. return np.sum(overdueTimes["还款状态值"]);
  224. #贷记卡24期还款记录次数
  225. def getPayRcdCount(payRcdDf,normalDf,month):
  226. payStatus = ["G", "D", "C", "N", "M", "1", "2", "3", "4", "5", "6", "7"]
  227. # 贷款24期还款记录次数 剔除结清 转出 呆账
  228. payRcdTimesDf = payRcdDf[payRcdDf['账户编号'].isin(normalDf['账户编号'].values)]
  229. payRcdTimesDf = payRcdTimesDf.sort_values(by=["账户编号", "还款日期"], ascending=(True, False))
  230. payRcdTimesDf = payRcdTimesDf.groupby(['账户编号']).head(month)
  231. # 从“贷款信息”中提取,剔除“账户状态”为结清、转出、呆账、呆帐后,各账户的还款次数统计“24个月(账户)还款状态”包含"G","D","C","N","M"及数字的个数,MAX(各账户的还款次数)
  232. payRcdTimesDf = payRcdTimesDf[payRcdTimesDf['还款状态'].isin(payStatus)]
  233. payRcdTimes = payRcdTimesDf.groupby(['账户编号'])['还款状态'].count()
  234. return np.max(payRcdTimes)
  235. #最近6个月有贷款还款记录的月份数
  236. def getPayRcdCountNew(payRcdDf,reportTime,month):
  237. # reportTime = str(np.datetime64(reportTime, "M")) + "-02"
  238. reportTime = utils.get_last_month_first_day_v2(reportTime)
  239. payDate = utils.getLastMonthDate(reportTime, month)
  240. # payRcdDfTmp = payRcdDf[payRcdDf['还款日期'] >= payDate]
  241. payRcdDfTmp = payRcdDf[(payRcdDf['还款日期'] > payDate) & (payRcdDf['还款日期'] <= reportTime)]
  242. payStatus = ["Z","G", "D", "C", "N", "M", "1", "2", "3", "4", "5", "6", "7"]
  243. payRcdTimesDf = payRcdDfTmp[payRcdDfTmp['还款状态'].isin(payStatus)]
  244. count = payRcdTimesDf["还款日期"].unique().size;
  245. return count