I really just can't grok how masks work in Numpy.
I create a mask like
import numpy
def make_mask(center_x,center_y,len_x,len_y):
x,y = numpy.ogrid[:len_x, :len_y]
mask = (center_x-x)**2 + (center_y-y)**2
return mask
Then I attempt to use it
>>>a = numpy.ones((10,10))
>>>mask = make_mask(2,2,2,2,2)
>>>a[mask] = 0
>>>a
array([[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[0,0,0,0,0,0,0,0],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[0,0,0,0,0,0,0,0],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[0,0,0,0,0,0,0,0]])
What I was expecting was something like
>>>a
array([[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[1,1,0,0,1,1,1,1],
[1,1,0,0,1,1,1,1],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1]])
I've try a few different versions of the function. I just can't get the desired behavior. What am I doing wrong. I really don't understand how a 2D matrix indexes a 2D matrix.
Your mask is setting the 2nd, 5th and 8th rows to 0; the array is being flattened since it does not have the same shape as the array it is masking. It is being applied as:
a[2] = 0
a[5] = 0
a[8] = 0
I think you were expecting something more like:
mask = numpy.ones_like(a)
mask[center_y:center_y + len_y, center_x:center_x + len_x] = 0
which has the same size as the array you are tring to mask and gives the expected result.
If you take a look at what your make_mask function does, when written like this:
def make_mask(index_x,index_y,len_x,len_y):
x,y = numpy.ogrid[:len_x, :len_y]
mask = (index_x-x)**2 + (index_y-y)**2
return mask
you will see that you get
array([[8, 5],
[5, 2]])
and when you index a 10x10 matrix with that 2x2 matrix, I believe it treats all the values in that matrix as indexing the larger matrix by row. Which is why you see the 2nd row with all zeros, the 5th row with all zeros and the 8th row with all zeros.
To get the effect you desire, you can just use the indices you have, you don't even need a function:
a[startx:startx+lenx, starty:starty+leny] = 0
which gives:
array([[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 0., 0., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 0., 0., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]])
Related
I have the code:
g, g_err = data[:, 4:6].T
I don't know the meaning of [:, 4:6]
especially the first :
and does .T mean transpose?
You have a 2D matrix called data, your code takes all elements from the first dimension, marked as :, then takes only elements 4 and 5 in the second dimension, something like this:
>>> np.ones( (7,7 ))
array([[ 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1.]])
>>> np.ones( (7,7 ))[:,4:6]
array([[ 1., 1.],
[ 1., 1.],
[ 1., 1.],
[ 1., 1.],
[ 1., 1.],
[ 1., 1.],
[ 1., 1.]])
>>>
And yeah, .T means transpose.
In [136]: d = np.ones((1,2,3,4))
In [167]: d[0][0][0:2][0]
Out[167]: array([ 1., 1., 1., 1.])
as shown above, why it's not returning exactly 2 elements
Look at the array itself. It should be self explanatory
>>> d
array([[[[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]],
[[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]]]])
# first you grab the first and only element
>>> d[0]
array([[[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]],
[[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]]])
# then you get the first element out of the two groups
>>> d[0][0]
array([[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]])
# thirdly, you get the two first elements as a list
>>> d[0][0][0:2]
array([[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]])
# finally, you get the first element of the list
>>> d[0][0][0:2][0]
array([ 1., 1., 1., 1.])
How can I add a small numpy array to a part of big numpy array?
My code is like:
import numpy as np
x = np.ones((10, 15))
I want to add a 3 by 3 np array to the middle or some location that I can designate.
If by adding you mean assigning values from 3x3 matrix into your x matrix, then you can assign it to the slice of your x matrix. Example -
x[row:row+3,col:col+3] = np.array([[1,2,3],[4,5,6],[7,8,9]]) #Your 3x3 array on right side.
Demo -
In [98]: x = np.ones((10,15))
In [99]: x[3:6,3:6] = np.array([[1,2,3],[4,5,6],[7,8,9]])
In [100]: x
Out[100]:
array([[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 1., 2., 3., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 4., 5., 6., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 7., 8., 9., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1.]])
If by add, you meant to add the values up at the corresponding indexes, you can use += in the above slicing assignment. Example -
x[row:row+3,col:col+3] += np.array([[1,2,3],[4,5,6],[7,8,9]]) #Your 3x3 array on right side.
My system is best described by a diagonal sparse matrix (Poisson). I have my diagonal sparse matrix, however, I want to change the boundary conditions (ie the "edges" of my matrix) to zero. It must be a common situation where a modeler wants to describe a system in a sparse diagonal matrix with distinct boundary conditions, is there a best practice for doing this?
[[0,0,0,0,..0],
[0,2,1,0,..0],
[0,1,2,1,..0],
...
[0,0,0,0,..0]]
It depends on which sparse matrix format you use. Apparently lil_matrix and dok_matrix can use slice assignments.
To construct a matrix efficiently, use either lil_matrix (recommended)
or dok_matrix. The lil_matrix class supports basic slicing and fancy
indexing with a similar syntax to NumPy arrays.
Which makes this rather easy:
In : x = scipy.sparse.lil_matrix(np.ones((6,6)))
In : x.todense()
Out:
matrix([[ 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1.]])
In : x[:, 0] = 0
In : x[:, -1] = 0
In : x[0, :] = 0
In : x[-1, :] = 0
In : x.todense()
Out:
matrix([[ 0., 0., 0., 0., 0., 0.],
[ 0., 1., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0.]])
PS: FYI, your matrix is called tridiagonal, not diagonal.
as a replacement value for another within an operation with arrays, or how to search within an array and replace a value by another
for example:
array ([[NaN, 1., 1., 1., 1., 1., 1.]
[1., NaN, 1., 1., 1., 1., 1.]
[1., 1., NaN, 1., 1., 1., 1.]
[1., 1., 1., NaN, 1., 1., 1.]
[1., 1., 1., 1., NaN, 1., 1.]
[1., 1., 1., 1., 1., NaN, 1.]
[1., 1., 1., 1., 1., 1., NaN]])
where it can replace NaN by 0.
thanks for any response
You could do this:
import numpy as np
x=np.array([[np.NaN, 1., 1., 1., 1., 1., 1.],[1., np.NaN, 1., 1., 1., 1., 1.],[1., 1., np.NaN, 1., 1., 1., 1.], [1., 1., 1., np.NaN, 1., 1., 1.], [1., 1., 1., 1., np.NaN, 1., 1.],[1., 1., 1., 1., 1., np.NaN, 1.], [1., 1., 1., 1., 1., 1., np.NaN]])
x[np.isnan(x)]=0
np.isnan(x) returns a boolean array which is True wherever x is NaN.
x[ boolean_array ] = 0 employs fancy indexing to assign the value 0 wherever the boolean array is True.
For a great introduction to fancy indexing and much more, see also the numpybook.
these days there is the special function:
a = numpy.nan_to_num(a)
Here is the example array in the question:
import numpy as np
a = np.where(np.eye(7), np.nan, 1)
You can either use numpy.where and numpy.isnan functions to create a new array b:
b = np.where(np.isnan(a), 0, a)
Or use an in-place function to directly modify the a array:
np.place(a, np.isnan(a), 0) # returns None