Remove nan from multidimensional numpy array - python

I have an array of shape (30,2,3).
Some of the entries will all contain np.nan
I would like to remove them. How can I do this?
Here is an example:
import numpy as np
arr = np.zeros((30,2,3))
arr[5:,:,:]=np.nan
# Expression to remove nan
arr = arr[~np.isnan(arr)] #this will not preserve the structure`

Since you're dealing with multidimensional array, you'll need to provide the correct axis value within the any():
import numpy as np
arr = np.zeros((30,2,3))
arr[5:,:,:]=np.nan
arr = arr[~np.isnan(arr).any(axis=(2,1))]
print(arr)
[[[0. 0. 0.]
[0. 0. 0.]]
[[0. 0. 0.]
[0. 0. 0.]]
[[0. 0. 0.]
[0. 0. 0.]]
[[0. 0. 0.]
[0. 0. 0.]]
[[0. 0. 0.]
[0. 0. 0.]]]

Related

Reversing numpy where coordinate

The objective is to extract the coordinate where a cell equal to 1 in a 2D array
[[1. 0. 0. 1. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 1. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0.]]
Here the coordinate is flip than the conventional
8
7
6
5
4
3
2
1
0
0 1 2 3 4 5 6 7 8
Hence, for the 2D array above,
the output where cell equal to 1 is
[(0, 8),(2,4),(3,8)]
I curious how can I tweak the np.where by taking consideration this type of coordinate.
Simply
cor=np.array(np.where(arr==1)).T
as expected will give different result than I expect.
The above array can be reproduce
arr=np.zeros((9,9))
arr[0,0]=1
arr[4,2]=1
arr[0,3]=1
Remark, the order is not important, such that
[(0, 8),(2,4),(3,8)] is equivalent to [(8, 0),(4,2),(8,3)]
The function np.where for a 2D array returns Tuple(np.ndarray, np.ndarray)where the first entry of the tuple contains all row indices and the second one all column indices. So if you want to index the tranposed array you have to swap the tuple entries:
indices = np.where(condition)[::-1]
If you want to transform the coordinate format to the list of 2-element-tuple you could do:
indices = [(n_rr, c) for r, c in zip(np.where(condition))]
Edit:
After clarification, I now understand that rpb wants to change the origin of indexing, so that the zeroth row becomes the last and so on. Furthermore, the coordinates are desired in the format of 2element tuple per found entry.
import numpy as np
arr=np.zeros((9,9))
arr[0,0]=1
arr[4,2]=1
arr[0,3]=1
print(arr)
print(np.where(arr==1.)[0])
n_rows = arr.shape[0]
indices = [(n_rows - 1 -r, c) for r, c in zip(*np.where(arr==1.))]
print(indices)
>>> [(8, 0), (8, 3), (4, 2)]
you can use numpy flip on axis 0 to flip the array to get your coordinates.
arr = np.flip(arr, axis=0)
cor = np.array(np.where(arr==1))

How to insert the entered numbers into the diagonal

As usual, was practicing python and got this exercise:
Create a 4 * 4 matrix with values of 1,2,3,4 on the main diagonal of the
array.
Input and output legend:
Enter your value: 4
[[1. 0. 0. 0.]
[0. 2. 0. 0.]
[0. 0. 3. 0.]
[0. 0. 0. 4.]]
Did this so far, not much yeah but can't get how to approach to this task
import numpy as ar
x = ar.zeros((4, 4))
x[::2, 1::2] = 0
x[1::2, ::2] = 0
print(x)
You could use np.fill_diagonal() documentation
import numpy as np
x = np.zeros((4, 4))
np.fill_diagonal(x, [1,2,3,4])
print(x)
Output:
[[1. 0. 0. 0.]
[0. 2. 0. 0.]
[0. 0. 3. 0.]
[0. 0. 0. 4.]]
Automatically using the number from your input:
import numpy as np
input_val = int(input('Enter your value:'))
x = np.zeros((input_val, input_val))
np.fill_diagonal(x, range(1,input_val+1))
print(x)
Output:

Randomizing Array Values

I have a 4x4 array.
Initially the values are all set to 0, however I want to change innermost 2x2 values to a random float.
a = np.zeros((4,4))
print(a)
a[1:3,1:3] = random.uniform(-1,1)
print(a)
Creates an output:
[[0. 0. 0. 0. ]
[0. 0.66529858 0.66529858 0. ]
[0. 0.66529858 0.66529858 0. ]
[0. 0. 0. 0. ]]
When the desired outcome would be:
[[0. 0. 0. 0. ]
[0. 0.random0 0.random1 0. ]
[0. 0.random2 0.random3 0. ]
[0. 0. 0. 0. ]]
You need to use the size argument to generate a 2 by 2 random matrix:
a[1:3,1:3] = random.uniform(-1,1,size=(2,2))

Why does reshape work differently for Transpose and return a new nd array?

Why does reshape return a new array when transposed and return view when not transposed? When does it return views and when a new array?
a = np.zeros((3,2))
b = a.T.reshape(3*2)
c = a.reshape(3*2)
print(a)
c[2] = 10000
b[0] = 10000
print(a)
print(b)
Result
[[0. 0.]
[0. 0.]
[0. 0.]]
[[ 0. 0.]
[10000. 0.]
[ 0. 0.]]
[10000. 0. 0. 0. 0. 0.]

Python: Appending dimensions to a bidimensional array

Suppose you have an array (m, m) and want to make it (n, n). For example, transforming a 2x2 matrix to a 6x6. So:
[[ 1. 2.]
[ 3. 4.]]
To:
[[ 1. 2. 0. 0. 0. 0.]
[ 3. 4. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]]
This is what I'm doing:
def array_append(old_array, new_shape):
old_shape = old_array.shape
dif = np.array(new_shape) - np.array(old_array.shape)
rows = []
for i in xrange(dif[0]):
rows.append(np.zeros((old_array.shape[0])).tolist())
new_array = np.append(old_array, rows, axis=0)
columns = []
for i in xrange(len(new_array)):
columns.append(np.zeros(dif[1]).tolist())
return np.append(new_array, columns, axis=1)
Example use:
test1 = np.ones((2,2))
test2 = np.zeros((6,6))
print array_append(test1, test2.shape)
Output:
[[ 1. 1. 0. 0. 0. 0.]
[ 1. 1. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]]
Based on this answer. But that's a lot of code for an (imho) simple operation. Is there a more concise/pythonic way to do it?
Why not use array = numpy.zeros((6,6)), see the numpy docs...
EDIT, woops, question has been edited... I guess you are trying to put ones in a section of an array filled with zeros? Then:
array = numpy.zeros((6,6))
array[0:2,0:2] = 1
If the small matrix does not all have the value of 1:
array[ystart:yend,xstart:xend] = smallermatrix
That would be then:
# test1= np.ones((2, 2))
test1= np.random.randn((2, 2))
test2= np.zeros((6, 6))
test2[0: 2, 0: 2]= test1

Categories