Как рассчитать сумму abs всех недиагональных элементов массива numpy? - PullRequest
0 голосов
/ 20 декабря 2018

Я новичок в numpy и хочу вычислить сумму abs всех недиагональных элементов массива numpy. недиагональные элементы матрицы - это все элементы матрицы, кроме тех, которые находятся в главной ее диагонали.

Я хочу вычислить сумму их абсолютных величин, чтобы я мог реализовать алгоритм собственных значений Якоби из этой лекции

поэтому, для вычисления, я думаю, что этот код будет работать:

import numpy as np
off_diagonal_sum = 0
for i in range(n): # n is the dimension of our square matrix
    # mat is our matrix
    off_diagonal_sum = off_diagonal_sum + np.sum(np.abs(mat[i, (i + 1):n]))
    off_diagonal_sum = off_diagonal_sum + np.sum(np.abs(mat[i, 0:(i - 1)]))

, но как яЯ новичок в NumPy, я думаю, что должен быть более простой и короткий способ вычислить это.у вас есть идеи?

спасибо заранее.

Ответы [ 2 ]

0 голосов
/ 21 декабря 2018

Вычитание трассы из полной суммы выполняется быстро и большую часть времени совершенно нормально.

Если, однако, недиагональные элементы намного (на много порядков) меньше, чем диагональные элементы, результаты могут статьнеточно.

Таким образом, вот два простых решения, которые не так быстро, но безопаснее.

# make an example with very small off-diag elements

from scipy.spatial.distance import squareform

N = 100
A = np.identity(N) + 1e-8*np.random.random((N, N))
A = np.abs(A+A.T) # A is symmetric, also we take the absolute value right here

# method 1
np.bincount(np.identity(N, int).ravel(), A.ravel())[0]
# 9.934386601640464e-05

# method 2 - this only works with symmetric A:
2*squareform(A, checks=False).sum()
# 9.934386601640431e-05

# and the "subtract trace" method
A.sum()-A.trace()
# 9.934386602594714e-05

# with double precision all looks ok in this example
# so for the sake of demonstration let's go to single precision
A = A.astype(np.single)

np.bincount(np.identity(N, int).ravel(), A.ravel())[0]
# 9.93438660777668e-05
2*squareform(A, checks=False).sum()
# 9.93438734440133e-05

# so far so good, but ...

A.sum()-A.trace()
# 7.6293945e-05

# Ouch!
0 голосов
/ 20 декабря 2018

В NumPy есть замечательная опция diag_indices , которая возвращает вам индексы диагональных элементов двумерного массива.Используя это, вы можете получить сумму диагональных элементов и вычесть ее из суммы полного массива np.sum(arr), чтобы получить сумму внедиагональных элементов без использования явных циклов for.Чтобы получить абсолютную сумму, вы просто используете np.abs, чтобы получить абсолютные значения каждого элемента, а затем выполните задачу следующим образом.

Пример

import numpy as np
arr = np.random.randint(1, 20, size=(3,3)) # Define a random 2d array
print (arr)
dia = np.diag_indices(3) # indices of diagonal elements
dia_sum = sum(arr[dia]) # sum of diagonal elements
off_dia_sum = np.sum(arr) - dia_sum # subtract the diagonal sum from total array sum
print (off_dia_sum)

[[12 19 10]
 [ 3 13 18]
 [16 16  6]]
82

Альтернатива 1

Вы также можете просто использовать np.trace, чтобы получить сумму диагональных элементов, а затем вычесть ее из общей суммы массива, чтобы получить сумму выкл.-диагональные элементы.

off_dia_sum = np.sum(arr) - np.trace(arr)

Альтернативные 2

Использование np.diagonal для получения диагональных элементов, а затем взять сумму и вычесть из общей суммы как

dia_sum = sum(np.diagonal(arr))
off_dia_sum = np.sum(arr) - dia_sum

Альтернативный 3

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

size = len(arr)
off_dia_sum = sum([arr[i][j] for i in range(size) for j in range(size) if i!=j])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...