Python pandas如何自动批量计算多阶段职业概率的全组合结果
问题描述
现有维度为4×10的pandas DataFrame,行对应1-10类职业(所有职业均属于其中一类),列存储数据库中人员第一、第二、第三、第四份工作分别属于10个职业类别的概率,原始数据如下:
import pandas as pd prob_all_dict = {'prob_1': {1.0: 0.03409090909090909, 2.0: 0.022727272727272728, 3.0: 0.045454545454545456, 4.0: 0.5340909090909091, 5.0: 0.06818181818181818, 6.0: 0.011363636363636364, 7.0: 0.13636363636363635, 8.0: 0.06818181818181818, 9.0: 0.045454545454545456, 10.0: 0.03409090909090909}, 'prob_2': {1.0: 0.045454545454545456, 2.0: 0.011363636363636364, 3.0: 0.03409090909090909, 4.0: 0.4659090909090909, 5.0: 0.11363636363636363, 6.0: 0.045454545454545456, 7.0: 0.1590909090909091, 8.0: 0.045454545454545456, 9.0: 0.03409090909090909, 10.0: 0.045454545454545456}, 'prob_3': {1.0: 0.1111111111111111, 2.0: 0, 3.0: 0.06349206349206349, 4.0: 0.3968253968253968, 5.0: 0.07936507936507936, 6.0: 0, 7.0: 0.19047619047619047, 8.0: 0.1111111111111111, 9.0: 0, 10.0: 0.047619047619047616}, 'prob_4': {1.0: 0, 2.0: 0, 3.0: 0.043478260869565216, 4.0: 0.391304347826087, 5.0: 0.13043478260869565, 6.0: 0, 7.0: 0.08695652173913043, 8.0: 0.2608695652173913, 9.0: 0, 10.0: 0.08695652173913043}} prob_all = pd.DataFrame.from_dict(prob_all_dict)
已通过单元格相乘生成DataFrame out:第一行存储第一份工作的概率,后续行存储第二份工作的条件概率(即已知第一份工作所属职业类别时,第二份工作属于各类别的概率),实现代码如下:
out=[prob_all['prob_1']]+[prob_all['prob_2']*prob_all['prob_1'].iloc[x] for x in range(0,10)] out=pd.concat(out,axis=1) out=(out.join(pd.concat([prob_all['prob_3']*out.iloc[x,1] for x in range(0,10)],axis=1)) .join(pd.concat([prob_all['prob_3']*out.iloc[x,2] for x in range(0,10)],axis=1),rsuffix='x') .join(pd.concat([prob_all['prob_3']*out.iloc[x,3] for x in range(0,10)],axis=1),rsuffix='x') .join(pd.concat([prob_all['prob_3']*out.iloc[x,4] for x in range(0,10)],axis=1),rsuffix='x') .join(pd.concat([prob_all['prob_3']*out.iloc[x,5] for x in range(0,10)],axis=1),rsuffix='x') .join(pd.concat([prob_all['prob_3']*out.iloc[x,6] for x in range(0,10)],axis=1),rsuffix='x') .join(pd.concat([prob_all['prob_3']*out.iloc[x,7] for x in range(0,10)],axis=1),rsuffix='x') .join(pd.concat([prob_all['prob_3']*out.iloc[x,8] for x in range(0,10)],axis=1),rsuffix='x') .join(pd.concat([prob_all['prob_3']*out.iloc[x,9] for x in range(0,10)],axis=1),rsuffix='x') .join(pd.concat([prob_all['prob_3']*out.iloc[x,10] for x in range(0,10)],axis=1),rsuffix='x') ).values out=pd.DataFrame(out).T
第三步需要计算已知前三次工作所属类别时,第四份工作属于1-10类的概率,覆盖全部1000种组合,当前手动编写运算逻辑效率极低,需要批量实现。
实现方案
直接利用numpy的广播机制完成批量计算,无需逐行编写逻辑,同时也可以优化之前生成out的冗余代码:
import numpy as np # 提取各阶段概率为numpy数组 p1 = prob_all['prob_1'].values.reshape(-1,1) # 第一份工作概率 shape(10,1) p2 = prob_all['prob_2'].values.reshape(1,-1) # 第二份工作概率 shape(1,10) p3 = prob_all['prob_3'].values.reshape(1,-1) # 第三份工作概率 shape(1,10) p4 = prob_all['prob_4'].values.reshape(1,-1) # 第四份工作概率 shape(1,10) # 计算前三次所有组合的联合概率:shape(10,10,10) = 1000种组合 joint_3 = p1[:, np.newaxis, np.newaxis] * p2[np.newaxis, :, np.newaxis] * p3[np.newaxis, np.newaxis, :] # 计算第四份工作的所有组合概率:shape(1000,10),每一行对应一种前三次组合的第四份工作10类概率 result = joint_3.reshape(-1,1) * p4 # 如果需要转成DataFrame,可添加对应索引便于查询 result_df = pd.DataFrame( result, index = pd.MultiIndex.from_product([range(1,11), range(1,11), range(1,11)], names=['第一份职业','第二份职业','第三份职业']), columns = [f'第四份职业_{i}' for i in range(1,11)] )
如果要直接基于你已经生成的out计算,也可以用一行代码完成:
result = out.values.reshape(-1,1) * prob_all['prob_4'].values.reshape(1,-1)
内容的提问来源于stack exchange,提问作者Theresa_S
相关产品推荐
相关产品推荐

