构建矩阵没有循环?

时间:2017-04-25 22:24:13

标签: python performance pandas numpy matrix

我试图避免在以下代码中使用循环,因为它很慢。我首先列出了标签列表和指标列表,其长度与几百万相同。然后我想制作一个对称的NxN矩阵,其中N是唯一标签值的数量(大约100)。矩阵包含度量的比较。具体来说,度量是一个列表列表,我想计算子列表中匹配元素的数量,并用该值更新输出矩阵。目前的代码是:

matrix = {}
for i,value_i in enumerate(labels):
    for j,value_j in enumerate(labels):
        if i >= j:       
            matrix[(value_i,value_j)] = matrix.get((value_i,value_j), 0) 
                                        + np.count_nonzero(metrics[i]==metrics[j])
            if i != j:
                matrix[(value_j,value_i)] = matrix[(value_i,value_j)] 

我想做列表理解之类的事情,但也想要一本字典因为我经常更新。对于上下文,我已经从更精细的代码here

中删除了这个

------- --------更新

授予@piRSquared建议使用numba的答案。增益来自于使用这个包而不是使用数组而不是dict。为了比较,以下是慢1.29倍。

f, u = pd.factorize(labels)
mx = f.max() + 1
matrix = np.zeros((mx, mx), np.int64)
for i in f:
    for j in f:
        if i >= j:
            matrix[i, j] = matrix[i, j] 
                           + np.count_nonzero(metrics[i] == metrics[j])
            if i != j:
                matrix[j, i] = matrix[i, j]
df = pd.DataFrame(matrix, u, u)                                         

1 个答案:

答案 0 :(得分:1)

我还在弄乱这个。这仍然是一个循环但我使用numba来加快速度。我将最终以更多信息充实这篇文章。但是,我现在想给你一些合作的东西。

我还有其他想法可以加快速度。

from string import ascii_uppercase
import numpy as np
import pandas as pd
from numba import njit

@njit
def fill(f, metrics):
    mx = f.max() + 1
    matrix = np.zeros((mx, mx), np.int64)
    for i in f:
        for j in f:
            if i >= j:
                row_i = metrics[i]
                row_j = metrics[j]
                matrix[i, j] = matrix[i, j] + (row_i == row_j).sum()
            if i != j:
                matrix[j, i] = matrix[i, j]
    return matrix


def fill_from_labels(labels, metrics):
    f, u = pd.factorize(labels)
    matrix = fill(f, metrics)
    return pd.DataFrame(matrix, u, u)

df = fill_from_labels(labels, metrics)