使用熊猫进行高效的成对计算

时间:2018-08-23 18:41:48

标签: python pandas loops dataframe iteration

鉴于分类数据的某些行,我想计算一个成对矩阵,其中包含这些行之间的差异数。

例如,将具有值[1, 0, 0, 1]的行与具有值[0, 0, 1, 1]的行进行比较,将得出结果值为2,因为索引0和2不同。

我想制作一个矩阵,显示每个成对组合的行。我为此编写了代码,但是在大数据上效率很低。我知道必须有一种更有效地执行此操作的方法,因为仅需要真正计算该矩阵的上半部分。

不过,我不知道如何将其转换为代码。这是我到目前为止的内容:

shortened = pd.DataFrame(
    [{'c1':1, 'c2':0, 'c3':0}, {'c1':1,'c2':1, 'c3':0}, {'c1':0,'c2':0, 'c3':1}]
)
distm = [[""]+ list(shortened.index)]
found = {}
for index,row in shortened.iterrows():
    newrow = [index]
    for i2,r2 in shortened.iterrows():
        if((i2,index) in found):
            newrow.append(found[(i2,index)])
            continue
        if(index == i2):
            newrow.append(0)
            continue
        summeddif = sum(i != j for i, j in zip(row, r2))
        newrow.append(summeddif)
        found[(index,i2)] = summeddif
    distm.append(newrow)

因此,以此处的数据帧示例为例,可以获得正确的输出:

  | 0 1 2
---------
0 | 0 1 2
1 | 1 0 3
2 | 2 3 0

但是,如果输入量很大,这将永远花费。是否有一种优雅的方法可以仅遍历上半部分,然后简单地复制到下半部分,因此我不需要进行不必要的比较?还是没有其他方法可以通过熊猫来改善这种状况?

1 个答案:

答案 0 :(得分:2)

使用广播的异或。

(shortened.values ^ shortened.values[:, None]).sum(2)

array([[0, 1, 2],
       [1, 0, 3],
       [2, 3, 0]])

XOR是检查两个位是否相同的最简单(也是最快)的方法。只要您的输入是二进制,这应该就可以工作。

请注意,这会占用大量内存,尤其是对于非常大的帧,有机会在〜1M行出现OOM。