Compter les éléments non-zéros dans chaque rangée et dans chaque colonne d'un tableau 2d NumPy

j'ai un NumPy matrice qui contient principalement des valeurs non-nulles, mais parfois contient une valeur zéro. J'ai besoin d'être en mesure de:

  1. compter les valeurs non nulles dans chaque rangée et mettre ce nombre dans une variable que je peux utiliser dans des opérations ultérieures, peut-être en itérant par des indices de rangée et en effectuant les calculs pendant le processus itératif.

  2. compter les valeurs non nulles dans chaque colonne et mettre ce nombre dans une variable que je peux utiliser dans des opérations ultérieures, peut-être en itérant par des indices de colonne et en effectuant les calculs pendant le processus itératif.

par exemple, une chose que je dois faire est de faire la somme de chaque ligne et puis diviser chaque somme de ligne par le nombre de valeurs non-zéro dans chaque ligne, en déclarant un résultat séparé pour chaque indice de ligne. Et puis je dois faire la somme de chaque colonne et puis diviser la somme de la colonne par le nombre de valeurs non-zéro dans la colonne, déclarant également un séparé résultat pour chaque index de colonne. J'ai besoin de faire d'autres choses aussi, mais il devrait être facile après j'ai trouver comment faire les choses que je suis d'inscription ici.

le code avec lequel je travaille est ci-dessous. Vous pouvez voir que je crée un tableau de zéros et puis le peupler à partir d'un csv fichier. Certains de ses lignes contiennent des valeurs pour toutes les colonnes, mais d'autres lignes encore quelques zéros en restant dans l'une des dernières colonnes, créant ainsi le problème décrit surtout.

Les cinq dernières lignes du code ci-dessous sont d'une autre publication sur ce forum. Ces cinq dernières lignes de code renvoient une liste imprimée d'indices ligne/colonne pour les zéros. Cependant, je ne sais pas comment utiliser cette information résultante pour créer les nombres de lignes non-zéro et les nombres de colonnes non-zéro décrits ci-dessus.

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

quelqu'un Peut-il m'aider?

18
demandé sur Pearly Spencer 2010-09-26 13:07:06

4 réponses

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)

la variable (a != 0) est un tableau de la même forme que l'original a et il contient True pour tous les éléments non-zéros.

.sum(x) la fonction additionne les éléments sur l'axe x. Somme de True/False éléments est le nombre de True éléments.

les variables columns et rows contient le nombre non-nul (élément != 0) valeurs dans chaque colonne / ligne de votre tableau original:

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

EDIT: L'ensemble du code pourrait ressembler à ceci (avec quelques simplifications dans le code):

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)

EDIT 2:

Pour obtenir la valeur moyenne de toutes les colonnes/lignes, utilisez la commande suivante:

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

Que voulez-vous faire si il n'y a pas non nulle éléments dans une colonne/ligne? Ensuite, nous pouvons adapter le code pour résoudre un tel problème.

28
répondu eumiro 2010-09-26 09:54:07

un moyen rapide de compter les éléments non nuls par ligne dans une matrice scipy clairsemée m est:

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

indptr attribut D'une matrice CSR indique les indices à l'intérieur des données correspondant aux limites entre les lignes. Ainsi, le calcul de la différence entre chaque entrée fournira le nombre d'éléments non-zéro dans chaque rangée.

de Même, pour le nombre d'éléments non nuls dans chaque colonne, utilisez:

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

Si les données sont déjà dans le formulaire approprié, ces O (m.shape[0]) et O (m.shape[1]) respectivement, plutôt que O (m.getnnz()) dans les solutions de Marat et Finn.

si vous avez besoin à la fois de la ligne et de la colonne nozero compte, et, disons,m est déjà un RSE, vous pouvez utiliser:

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

qui n'est pas asymptotiquement plus rapide que la première conversion en CSC (qui est O (m.getnnz())) pour obtenir col_nonzeros, mais est plus rapide en raison de la mise en œuvre détail.

12
répondu joeln 2013-05-06 04:51:43

Le plus rapide est de cloner votre matrice, à la place de vraies valeurs. Alors résumez par lignes ou colonnes:

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

modifier: Peut-être aurez-vous besoin de traduire NumNonZeroElementsByColumn en 1-dimensional array par

np.array(NumNonZeroElementsByColumn)[0]
2
répondu Marat Zaynutdinoff 2012-07-29 14:23:52

(a != 0) ne fonctionne pas pour les matrices éparses (scipy.clairsemé.lil_matrix) dans ma version actuelle de scipy.

Pour les matrices creuses j'ai fait:

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

je me demande s'il y a une façon plus élégante.

0
répondu Finn Årup Nielsen 2012-07-09 12:39:21