Подсчет ненулевых элементов в каждой строке и в каждом столбце двумерного массива NumPy - PullRequest
20 голосов
/ 26 сентября 2010

У меня есть матрица NumPy, которая содержит в основном ненулевые значения, но иногда будет содержать нулевое значение. Мне нужно уметь:

  1. Подсчитайте ненулевые значения в каждой строке и поместите это число в переменную, которую я могу использовать в последующих операциях, возможно, путем итерации по индексам строк и выполнения вычислений во время итерационного процесса.

  2. Подсчитайте ненулевые значения в каждом столбце и поместите этот счет в переменную, которую я могу использовать в последующих операциях, возможно, путем итерации по индексам столбцов и выполнения вычислений во время итерационного процесса.

Например, одну вещь, которую мне нужно сделать, - это суммировать каждую строку, а затем делить сумму каждой строки на количество ненулевых значений в каждой строке, сообщая отдельный результат для каждого индекса строки. А затем мне нужно сложить каждый столбец, а затем разделить сумму столбцов на количество ненулевых значений в столбце, а также сообщить отдельный результат для каждого индекса столбца. Мне нужно делать и другие вещи, но они должны быть легкими после того, как я пойму, как делать вещи, которые я перечисляю здесь.

Код, с которым я работаю, приведен ниже. Вы можете видеть, что я создаю массив нулей, а затем заполняю его из файла 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 ]

30 голосов
/ 26 сентября 2010
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 элементов.

Переменные columns и rows содержат количество ненулевых (элемент! = 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)

Что вы хотите сделать, если в столбце / строке нет ненулевых элементов?Затем мы можем адаптировать код для решения такой проблемы.

17 голосов
/ 06 мая 2013

Быстрый способ подсчета ненулевых элементов на строку в скудной разреженной матрице m:

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

Атрибут indptr матрицы CSR указывает индексы в данных, соответствующих границаммежду рядами.Таким образом, вычисление разницы между каждой записью даст количество ненулевых элементов в каждой строке.

Аналогично, для количества ненулевых элементов в каждом столбце используйте:

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

Еслиданные уже в соответствующей форме, они будут работать в O (m.shape[0]) и O (m.shape[1]) соответственно, а не O (m.getnnz())) в решениях Марата и Финна.

Если вам нужно как число строк, так и число столбцов, и, скажем, m уже является CSR, вы можете использовать:

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

который не асимптотически быстрее, чем первое преобразование в CSC (то есть O (m.getnnz()) ), чтобы получить col_nonzeros, но быстрее из-за деталей реализации.

2 голосов
/ 29 июля 2012

Более быстрый способ - клонировать матрицу вместо реальных значений.Затем просто суммируйте по строкам или столбцам:

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

Это сработало для меня в 50 раз быстрее, чем решение Финна Орупа Нильсена (1 секунда против 53)

edit: Возможно, вы это сделаетенеобходимо перевести NumNonZeroElementsByColumn в одномерный массив с помощью

np.array(NumNonZeroElementsByColumn)[0]
0 голосов
/ 11 июня 2019

Для разреженных матриц используйте функцию getnnz(), поддерживаемую матрицей CSR / CSC.

Например,

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

array([0, 2, 1])
0 голосов
/ 03 мая 2012

(a! = 0) не работает для разреженных матриц (scipy.sparse.lil_matrix) в моей текущей версии scipy.

Для разреженных матриц я сделал:

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

Интересно, есть ли более элегантный способ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...