编程语言
首页 > 编程语言> > 使用Python进行高效的大规模比赛评分

使用Python进行高效的大规模比赛评分

作者:互联网

考虑包含以下条目的得分S的大数据框.每行代表参与者A,B,C和D的子集之间的比赛.

 A     B    C   D
0.1  0.3  0.8    1
  1  0.2  NaN  NaN
0.7  NaN    2  0.5
NaN   4   0.6  0.8

读取上面矩阵的方法是:观察第一行,参与者A在那一轮得分为0.1,B得分为0.3,依此类推.

我需要建立一个三角矩阵C,其中C [X,Y]存储参与者X比参与者Y好多少.更具体地说,C [X,Y]将保留X和Y之间分数的平均百分比差异.

从上面的示例:

C[A,B] = 100 * ((0.1 - 0.3)/0.3 + (1 - 0.2)/0.2) = 33%

我的矩阵S很大,所以我希望利用numpy或pandas中的JIT(Numba?)或内置方法.我当然想避免产生嵌套循环,因为S具有数百万行.

上面的有效算法是否有名称?

解决方法:

让我们看一下基于NumPy的解决方案,因此假设输入数据在名为a的数组中.现在,四个这样的变量的成对组合的数量将是4 * 3/2 =6.我们可以使用np.triu_indices()生成与此类组合相对应的ID.然后,使用这些索引对a的列进行索引.我们执行减法和除法运算,然后简单地添加忽略期望值输出为np.nansum()的NaN影响结果的列.

因此,我们将有一个这样的实现-

R,C = np.triu_indices(a.shape[1],1)
out = 100*np.nansum((a[:,R] - a[:,C])/a[:,C],0)

样品运行-

In [121]: a
Out[121]: 
array([[ 0.1,  0.3,  0.8,  1. ],
       [ 1. ,  0.2,  nan,  nan],
       [ 0.7,  nan,  2. ,  0.5],
       [ nan,  4. ,  0.6,  0.8]])

In [122]: out
Out[122]: 
array([ 333.33333333, -152.5       ,  -50.        ,  504.16666667,
        330.        ,  255.        ])

In [123]: 100 * ((0.1 - 0.3)/0.3 + (1 - 0.2)/0.2) # Sample's first o/p elem
Out[123]: 333.33333333333337

如果您需要将输出作为(4,4)数组,则可以使用Scipy's squareform

In [124]: from scipy.spatial.distance import squareform

In [125]: out2D = squareform(out)

让我们转换为熊猫数据框以获得良好的视觉反馈-

In [126]: pd.DataFrame(out2D,index=list('ABCD'),columns=list('ABCD'))
Out[126]: 
            A           B           C    D
A    0.000000  333.333333 -152.500000  -50
B  333.333333    0.000000  504.166667  330
C -152.500000  504.166667    0.000000  255
D  -50.000000  330.000000  255.000000    0

让我们手动计算[B,C]并返回查看-

In [127]: 100 * ((0.3 - 0.8)/0.8 + (4 - 0.6)/0.6)
Out[127]: 504.1666666666667

标签:pandas,matrix,numba,python,numpy
来源: https://codeday.me/bug/20191118/2025519.html