Подтвердить что ты не робот

Подсчет ненулевых элементов в каждой строке и в каждом столбце двумерного массива NumPy

У меня есть матрица 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))

Кто-нибудь может мне с этим помочь?

4b9b3361

Ответ 1

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 содержат число ненулевых значений (element!= 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)

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

Ответ 2

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

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

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

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

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

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

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

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

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

Ответ 3

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

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

Это работало в 50 раз быстрее, чем финн Årup Nielsen (1 секунда против 53)

изменить: Возможно, вам нужно будет перевести NumNonZeroElementsByColumn в 1-мерный массив на

np.array(NumNonZeroElementsByColumn)[0]

Ответ 4

(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.

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

Ответ 5

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

Например

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

array([0, 2, 1])