条件分案

2019-07-24  本文已影响0人  这是沸羊羊的干爹

分析建模,日常问题整理(二十七)


2019.7.31~2019.8.5

'''
目标:
对催收人员进行考核时
指标为回收金额
对分案人员应进行公平分配
公平的标准包括金额一致、户数一致、难度一致
以下分配主要保证户数相差不大,金额尽可能一致
难度一致打算进行数据建模
以是否回收为y
以产品信息、个人信息等为x
对案件打分
根据分数公平分配

解决:
利用排序
每次分案都是按上次从小到大的排序
对本次的金额从大到小的分配

存在问题:
不能达到金额一致的公平
因上班天数越多
分的案件金额越大
不能达到天平均金额一致
因案件量大时没有来上班参与分案
案件量小时却参与了
那平均分得的案件和平均金额也会变少
'''
def Allocation(history,his_loannum ,cases,todayname,date_):
    '''
    input:
    历史每天分案总额
    历史每天分案单号
    当前案件
    当前分案人员
    日期
    output:
    每天分案总额
    每天分案单号
    '''
    assert type(history) == type(pd.DataFrame())
    assert type(cases) == type(pd.DataFrame())
    num_cases = len(cases)
    cases.columns=[0,1]
    today_hm = history[history['人员'].isin(todayname)].reset_index(drop=True)
    tem_l = [ i for i in todayname if i not in history['人员'].tolist()]
    tem_n = [ i for i in todayname if i in history['人员'].tolist()]
    for k in tem_l:
        today_hm.loc[today_hm.shape[0]] = [k]+[0]*(history.shape[1]-1)
    if len(tem_n)!=0:
        for m in today_hm.columns[1:]:
            t_m = today_hm[m].sum()/(today_hm[m]!=0).sum()  # 将0填充为均值
            today_hm[m] = today_hm[m].replace(0,t_m)      
            
    num_people = len(today_hm)
    residue = num_people-num_cases%num_people   # 要补上的0的个数
    epoc = int(num_cases/num_people)+1  # 每人应当分配的案件量
    loan_num = pd.DataFrame(today_hm['人员'])
    loan_num = loan_num.set_index('人员')
    
    for gap in range(residue):
        cases.loc[num_cases+gap] = 0  # 在loan_no:应还总额的数据中添加要补上的0的n行

    cases = cases.sort_values(cases.columns[1], ascending=False).reset_index(drop=True)  ##对金额排序
    # del cases['index']
    for i in range(epoc):  # 每人要分配epoc个案件,按顺序分,分epoc次
        today_hm = today_hm.sort_index()
        today_hm['sum']  = today_hm.apply(lambda x:sum(x[1:]),axis=1) # 每次分配都要重新排序
        today_hm = today_hm.sort_values('sum', ascending = True)
        loan_num = loan_num.ix[today_hm['人员']]
        loan_num['idx_{}'.format(i)] = cases.iloc[i*num_people:(i+1)*num_people,0].values  #将这一次分配的loan_no保存
        today_hm['amt_{}'.format(i)] = cases.iloc[i*num_people:(i+1)*num_people,1].values   ##将这一次分配的repay_amt保存
        del today_hm['sum']
        
    today_hm = today_hm.sort_index()
    today_hm[date_]  = today_hm.apply(lambda x:sum(x[-epoc:]),axis=1) 
    today_hm.drop(today_hm.columns.tolist()[-(epoc+1):-1],axis=1,inplace=True)   

    loan_num = loan_num.reset_index()
    loan_num[date_] = loan_num.apply(lambda x:[x for x in x[1:].values.tolist() if x!=0],axis=1)
    loan_num.drop(loan_num.columns.tolist()[-(epoc+1):-1],axis=1,inplace=True)
    # res2.set_index('人员')['loan_lst'].to_dict()
    loan_num = loan_num.merge(his_loannum,on='人员',how='outer').fillna(0)
    today_hm = today_hm[['人员',date_]].merge(history,on='人员',how='outer').fillna(0)
    return today_hm,loan_num

from sympy import *
def assiged_random(dat,name_lst,date_):
    '''
    第一天随机分配
    初始化
    如果固定某一天则可以自动化实现
    '''
    assiged_dic = OrderedDict()
    his_amt=  pd.DataFrame()
    his_no = pd.DataFrame()
    loan_ = []
    n=len(name_lst)
    dat['REPAY_AMT'] = dat['REPAY_AMT'].astype(float)
    x,y = Symbol('x'),Symbol('y')
    a = int(dat.shape[0]/n)
    b = int(dat.shape[0]/n+1)
    solve_ = solve([a* x+b*y-dat.shape[0], x + y - n],[x, y])
    for i in range(0,n):
        if i<solve_[x]:
            dat_ix = random.sample(dat['ID_'].tolist(),a)
            loan_.extend(dat_ix)
            tem = dat[dat.ID_.isin(dat_ix)][['ID_','REPAY_AMT']]
            assiged_dic.update({name_lst[i]:{'ID_':dat_ix,'REPAY_AMT':tem['REPAY_AMT'].tolist()}})
            dat = dat[~dat.ID_.isin(loan_)].reset_index(drop = True)
        else :
            dat_ix = random.sample(dat['ID_'].tolist(),b)
            loan_.extend(dat_ix)
            tem = dat[dat.ID_.isin(dat_ix)][['ID_','REPAY_AMT']]
            assiged_dic.update({name_lst[i]:{'ID_':dat_ix,'REPAY_AMT':tem['REPAY_AMT'].tolist()}})
            dat = dat[~dat.ID_.isin(loan_)].reset_index(drop = True)
    his_amt = pd.DataFrame([[k,sum(assiged_dic[k]['REPAY_AMT'])] for k in assiged_dic.keys()],columns=['人员',date_])
    his_no = pd.DataFrame([[k,assiged_dic[k]['ID_']] for k in assiged_dic.keys()],columns=['人员',date_])
    return assiged_dic,his_amt,his_no


# 这一步之前要先初始化分配
hm = pd.DataFrame([['a',3,2],['b',4,3],['c',5,5],['d',6,1],['e',7,2]],columns=['人员','20190706','20190707'])
cs = pd.DataFrame([['A',3],['B',4],['C',5],['D',6],['E',7],['F',2],['G',8],['H',4],['I',6],['J',1],['K',9]])
res1,res2 = Allocation(hm, pd.DataFrame([['a','AA'],['b','BB'],['c','CC'],['d','DD'],['e','EE']],columns=['人员','20190707']),cs,hm['人员'].tolist()+['n'],'21090708')

res1['sum']  = res1.apply(lambda x:sum(x[1:-1]),axis=1) 
res1['sum_averge']  = res1.apply(lambda x:sum(x[1:])/((x!=0).sum()-1),axis=1) 
res2['sum'] = res2.iloc[:,1:].apply(lambda x:sum(list(map(lambda y:len(y) if y!=0 else 0,x))),axis=1)
上一篇 下一篇

猜你喜欢

热点阅读