在大型2D numpy数组

时间:2017-09-21 10:11:38

标签: python arrays numpy scipy sparse-matrix

我有一个2D numpy数组,有数十万行和一千个左右的列(假设它是一个N x P数组,N = 200,000,P = 1000)。这里的目标是计算每对行向量之间相同元素的数量,理想情况下使用numpy数组魔术,不需要我执行199,999 * 100,000个这样的对的循环。由于存储200,000×200,000阵列可能不可行,因此输出可能是Nx3稀疏坐标格式,例如,如果输入格式为:

5 12 14 200   0 45223
7 12 14   0 200 60000
7  6 23   0   0 45223
5  6 14 200   0 45223

得到的(密集的)NxN矩阵M将是(不关心对角线元素):

0 2 2 4
2 0 2 1
2 2 0 3
4 1 3 0

假设基于0的索引,Mij包含初始行i和初始行j之间的相同元素的数量。 因此,预期的稀疏输出等效值将是:

0 1 2
0 2 2
0 3 4
1 2 2 
1 3 1
2 3 3

实现这一目标的一种天真,非常低效的方式是:

import itertools
import numpy as np

def pairwise_identical_elements(small_matrix):
    n, p = small_matrix.shape
    coordinates = itertools.combinations(range(n), 2)
    sparse_coordinate_matrix = []
    for row1, row2 in itertools.combinations(small_matrix, 2):
        idx1, idx2 = next(coordinates)
        count = p - np.count_nonzero(row1 - row2)
        sparse_coordinate_matrix.append([idx1, idx2, count])
    return sparse_coordinate_matrix

我已经研究了距离度量实现,例如scipy和sklearn中的Jaccard相似性,但它们都假设输入行向量必须是二进制的。我还尝试添加第三个维度以使条目成为二进制(例如,条目'9'成为零的向量,在第9个位置具有1)但是存在明显的内存问题(条目'45223'将需要第三维伸展那么多元素。)

是否存在一种高效,可扩展和/或pythonic的解决方案,使用numpy或scipy以我错过的方式?

编辑:在进一步研究scipy后,我发现了一些与我正在尝试的内容非常匹配的东西,即scipy.sparse.distance.pdist和Hamming指标。然而,它以“压缩”的形式返回输出,并且由于我们试图避免转换为完全密集的数组以节省内存,因此问题可能变成:如何将压缩距离矩阵转换为稀疏矩阵?

1 个答案:

答案 0 :(得分:0)

如评论中所述,考虑到空间和CPU时间,scipy的pdist带有'汉明'是解决此问题的最简单有效的方法。

您将无法获得比其condensed output更高效的内存。 确实,与“ (N*(N-1)/2, 3)返回的N*(N-1)/2向量相比,以“稀疏”格式写入数据时,需要一个pdist矩阵。