计算2D NumPy数组中每行和每列内的非零元素

时间:2010-09-26 09:07:06

标签: python arrays count numpy

我有一个NumPy矩阵,主要包含非零值,但有时会包含零值。我需要能够:

  1. 计算每一行中的非零值,并将该计数放入我可以在后续操作中使用的变量中,可能是通过迭代行索引并在迭代过程中执行计算。

    < / LI>
  2. 计算每列中的非零值,并将该计数放入我可以在后续操作中使用的变量中,可能通过迭代列索引并在迭代过程中执行计算。

    < / LI>

    例如,我需要做的一件事是对每一行求和,然后将每行和除以每行中的非零值的数量,为每个行索引报告单独的结果。然后我需要对每列进行求和,然后将列总和除以列中非零值的数量,同时为每个列索引报告单独的结果。我还需要做其他事情,但在我弄清楚如何处理我在这里列出的事情后,它们应该很容易。

    我正在使用的代码如下。您可以看到我正在创建一个零数组,然后从csv文件中填充它。某些行将包含所有列的值,但其他行仍会在某些最后一列中保留一些零,从而产生上述问题。

    以下代码的最后五行来自此论坛的另一篇帖子。最后五行代码返回零的行/列索引的打印列表。但是,我不知道如何使用该结果信息来创建上述的非零行计数和非零列计数。

    ANOVAInputMatrixValuesArray=zeros([len(TestIDs),9],float)
    j=0
    for j in range(0,len(TestIDs)):
        TestID=str(TestIDs[j])
        ReadOrWrite='Read'
        fileName=inputFileName
        directory=GetCurrentDirectory(arguments that return correct directory)
        inputfile=open(directory,'r')
        reader=csv.reader(inputfile)
        m=0
        for row in reader:
            if m<9:
                if row[0]!='TestID':
                    ANOVAInputMatrixValuesArray[(j-1),m]=row[2]
                    m+=1
        inputfile.close()
    
    IndicesOfZeros = indices(ANOVAInputMatrixValuesArray.shape) 
    locs = IndicesOfZeros[:,ANOVAInputMatrixValuesArray == 0]
    pts = hsplit(locs, len(locs[0]))
    for pt in pts:
        print(', '.join(str(p[0]) for p in pt))
    

    任何人都可以帮我吗?

5 个答案:

答案 0 :(得分:30)

import numpy as np

a = np.array([[1, 0, 1],
              [2, 3, 4],
              [0, 0, 7]])

columns = (a != 0).sum(0)
rows    = (a != 0).sum(1)

变量(a != 0)是一个与原始a形状相同的数组,它包含所有非零元素的True

.sum(x)函数对轴x上的元素求和。 True/False元素的总和是True元素的数量。

变量columnsrows包含原始数组的每列/每行中的非零(元素!= 0)值的数量:

columns = np.array([2, 1, 3])
rows    = np.array([2, 3, 1])

编辑:整个代码看起来像这样(原始代码中有一些简化):

ANOVAInputMatrixValuesArray = zeros([len(TestIDs), 9], float)
for j, TestID in enumerate(TestIDs):
    ReadOrWrite = 'Read'
    fileName = inputFileName
    directory = GetCurrentDirectory(arguments that return correct directory)
    # use directory or filename to get the CSV file?
    with open(directory, 'r') as csvfile:
        ANOVAInputMatrixValuesArray[j,:] = loadtxt(csvfile, comments='TestId', delimiter=';', usecols=(2,))[:9]

nonZeroCols = (ANOVAInputMatrixValuesArray != 0).sum(0)
nonZeroRows = (ANOVAInputMatrixValuesArray != 0).sum(1)

编辑2

要获取所有列/行的平均值,请使用以下命令:

colMean = a.sum(0) / (a != 0).sum(0)
rowMean = a.sum(1) / (a != 0).sum(1)

如果列/行中没有非零元素,您想要做什么?然后我们可以调整代码来解决这个问题。

答案 1 :(得分:16)

在scipy稀疏矩阵m中计算每行非零元素的快速方法是:

np.diff(m.tocsr().indptr)

CSR矩阵的indptr属性指示数据中与行之间的边界对应的索引。因此,计算每个条目之间的差异将提供每行中非零元素的数量。

同样,对于每列中的非零元素数,请使用:

np.diff(m.tocsc().indptr)

如果数据已经采用适当的格式,则这些数据将分别在 O(m.shape[0] O(m.shape[1]中运行,而不是Marat和Finn解决方案中的 O(m.getnnz()

如果您需要行和列nozero计数,并且,例如,m已经是CSR,您可以使用:

row_nonzeros = np.diff(m.indptr)
col_nonzeros = np.bincount(m.indices)

并不比第一次转换到CSC( O(m.getnnz())更快地获得col_nonzeros,但由于实现细节而更快。

答案 2 :(得分:2)

更快的方法是使用1而不是实际值来克隆矩阵。然后只按行或列总结:

X_clone = X.tocsc()
X_clone.data = np.ones( X_clone.data.shape )
NumNonZeroElementsByColumn = X_clone.sum(0)
NumNonZeroElementsByRow = X_clone.sum(1)

对我而言,这比FinnÅrupNielsen的解决方案快了50倍(1秒对53)

编辑: 也许你需要通过

将NumNonZeroElementsByColumn翻译成一维数组
np.array(NumNonZeroElementsByColumn)[0]

答案 3 :(得分:0)

在我目前的scipy版本中,

(a!= 0)对稀疏矩阵(scipy.sparse.lil_matrix)不起作用。

对于稀疏矩阵,我做了:

    (i,j) = X.nonzero()
    column_sums = np.zeros(X.shape[1])
    for n in np.asarray(j).ravel():
        column_sums[n] += 1.

我想知道是否有更优雅的方式。

答案 4 :(得分:0)

对于稀疏矩阵,请使用CSR / CSC矩阵支持的getnnz()函数。

例如

a = scipy.sparse.csr_matrix([[0, 1, 1], [0, 1, 0]])
a.getnnz(axis=0)

array([0, 2, 1])