计算2D numpy阵列中每行内和每列内的非零元素

问题描述:

我有一个numpy矩阵,其中大多包含非零值,但偶尔会包含零值。我需要能够:
1.)计算每行中的非零值,并将该计数放入一个变量中,我可以在随后的操作中使用该变量,可能是迭代遍历行索引并在迭代过程中执行计算过程
2.)计数在每列中的非零值,并把该计数到我可以在后续操作中使用,也许通过列索引进行迭代,并且在迭代过程计算2D numpy阵列中每行内和每列内的非零元素

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

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

以下代码的最后5行来自本论坛的另一篇文章,最后5行代码返回打印的零/行索引列表。但我不知道如何使用结果信息创建上述的非零行数和非零列数。谁能帮我这个?

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)) 
+0

真是啰嗦问一个很大的问题。 – dbliss 2015-05-09 03:06:49

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]) 

EDIT:整个代码可能看起来像这(与原来的代码的一些简化):

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

'a.astype(bool)'将比'a!= 0'更快地工作(至少在int上) – joeln 2013-05-06 03:48:14

(a!= 0)在我现有版本的scipy中对稀疏矩阵(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. 

我不知道是否有一个更优雅的方式。

更快的方法是克隆你的矩阵而不是真正的值。然后,只需按行或列总结:这工作快50倍,我不是芬兰人奥雅纳尼尔森的解决方案(1票反对53秒)

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

编辑: 也许你会需要NumNonZeroElementsByColumn翻译成1维阵列由

np.array(NumNonZeroElementsByColumn)[0] 

一种快速的方法来计算每行的非零元素在SciPy的稀疏矩阵m是:

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

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

类似地,对于每一列的非零元素的数目,可使用:

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

如果数据已经在适当的形式,这些都将在O(m.shape[0]ö运行(m.shape[1],而不是O(m.getnnz()在Marat和Finn的解决方案中。

如果需要行和列nozero计数,并说,m已经是一个CSR,你可以使用:

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

这是不是渐近速度比第一转化为CSC(这是Ø (m.getnnz())得到col_nonzeros,但由于实现细节更快。

+1

'scipy.sparse.csr_matrix'和'csc_matrix'现在支持'getnnz(axis = 0)'和'getnnz (轴= 1)'使用这种方法。 – joeln 2015-09-27 01:03:49