Performing operations on a NumPy arrray but masking values along the diagonal from these operations
as I c开发者_运维百科an perform operations on arrays so that does nothing on the diagonal is calculated such that all but the diagonal
array ([[0., 1.37, 1., 1.37, 1., 1.37, 1.]
[1.37, 0. , 1.37, 1.73, 2.37, 1.73, 1.37]
[1. , 1.37, 0. , 1.37, 2. , 2.37, 2. ]
[1.37, 1.73, 1.37, 0. , 1.37, 1.73, 2.37]
[1. , 2.37, 2. , 1.37, 0. , 1.37, 2. ]
[1.37, 1.73, 2.37, 1.73, 1.37, 0. , 1.37]
[1. , 1.37, 2. , 2.37, 2. , 1.37, 0. ]])
to avoid the NaN value, but retained the value zero on the diagonal in all responses
I wonder if masked arrays might do what you want, e.g.,
import numpy as NP
A = NP.random.random_integers(0, 9, 16).reshape(4, 4)
dg = NP.r_[ [NP.nan] * 4 ] # proper syntax is 'nan' not 'NaN'
dg = NP.diag(dg)
A += dg # a 4x4 array w/ NaNs down the main diagonal
NP.sum(A, axis=1) # doesn't work, gives: array([ NaN, NaN, NaN, NaN])
from numpy import ma as MA
Am = **MA.masked_invalid**(A)
NP.sum(Am, axis=1) # now it works (treats 'nan' as 0)
The other way to do this of is, of course, to first convert the NaNs to 0s then mask the 0s:
NP.nan_to_num(A)
MA.masked_equal(A, 0)
Finally, it's often efficient to mask and convert the NaNs in one step:
MA.fix_invalid(A)
Pretty straightforward, just keep in mind that 'ma' might not yet be in your namespace and also that these functions deal with 'NaNs' and 'infs', which is usually what you want.
>>> arr = [
... [0., 1.37, 1., 1.37, 1., 1.37, 1.],
... [1.37, 0. , 1.37, 1.73, 2.37, 1.73, 1.37],
... [1. , 1.37, 0. , 1.37, 2. , 2.37, 2. ],
... [1.37, 1.73, 1.37, 0. , 1.37, 1.73, 2.37],
... [1. , 2.37, 2. , 1.37, 0. , 1.37, 2. ],
... [1.37, 1.73, 2.37, 1.73, 1.37, 0. , 1.37],
... [1. , 1.37, 2. , 2.37, 2. , 1.37, 0. ]
... ]
>>> for i in range(6):
... for y in range(6):
... if (i <> y):
... print arr[i][y]*arr[y][i]
...
1.8769
1.0
1.8769
1.0
1.8769
1.8769
1.8769
2.9929
5.6169
2.9929
1.0
1.8769
1.8769
4.0
5.6169
1.8769
2.9929
1.8769
1.8769
2.9929
1.0
5.6169
4.0
1.8769
1.8769
1.8769
2.9929
5.6169
2.9929
1.8769
Depends on what you need to calculate
Do your calculation as normal and then
myarray[arange(len(array)), arange(len(array))] = 0.
Can you just do the calculation as normal, then afterwards set the diagonal back to zero?
精彩评论