Concatenate only extant non-empty numpy arrays? - arrays

This should be easy...
I want to concatenate arrays A, B and C. It is possible that one or more of them may not exist or be empty. I want the remaining arrays to be concatenated. If, for example, B is empty, I want to concatenate A with C.
I've read these questions that seem relevant:
How can I check whether the numpy array is empty or not?
How do you 'remove' a numpy array from a list of numpy arrays?
I assume there's a 1-2 line way to do this.

Concatenating empty arrays is not a problem:
In [1]: a = np.arange(10)
In [2]: b = np.array([])
In [3]: c = np.arange(3)
In [4]: np.concatenate((a,b,c))
Out[4]: array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 0., 1., 2.])
For 2D arrays:
In [1]: a = np.arange(12.0).reshape((4,3))
In [2]: b = np.arange(24.0).reshape((8,3))
In [3]: c = np.array([])
In [4]: np.concatenate([x for x in [a,b,c] if x.size > 0])
Out[4]:
array([[ 0., 1., 2.],
[ 3., 4., 5.],
[ 6., 7., 8.],
[ 9., 10., 11.],
[ 0., 1., 2.],
[ 3., 4., 5.],
[ 6., 7., 8.],
[ 9., 10., 11.],
[ 12., 13., 14.],
[ 15., 16., 17.],
[ 18., 19., 20.],
[ 21., 22., 23.]])

Related

How can i create 2 for loops to replace values in Numpy array?

How can i use two for loops to replace the values in x with the row number, starting at 1, so it should be [[1,1,1,1,1],[2,2,2,2,2] … [5,5,5,5,5]]
x=np.ones((5,5))
print(x)
Thanks
Don't use for loops in numpy, use broadcasting:
x=np.ones((5,5))
x[:] = np.arange(x.shape[0])[:, None]+1
Updated x:
array([[1., 1., 1., 1., 1.],
[2., 2., 2., 2., 2.],
[3., 3., 3., 3., 3.],
[4., 4., 4., 4., 4.],
[5., 5., 5., 5., 5.]])
Alternatives:
x[:] = np.arange(x.shape[0])[:, np.newaxis]+1
Or:
x[:] = np.arange(x.shape[0]).reshape(-1, 1)+1

creating numpy matrix from nested arrays in a list

I have a list as follows.
list=[[np.array([[-3., 3., 3.],
[-3., 3., 3.],
[-3., 3., 3.],
[ 1., 4., 2.],
[-0., 4., -5.],
[ 3., 6., -5.]])],
[np.array([[-1., 2., -3.],
[-1., 2., -3.],
[-1., 2., -3.],
[-2., 2., 1.],
[-0., 4., -0.],
])]]
The list contains numpy array. It should be noted that the number of rows in each numpy array is different but the number of columns are same. As in the example, the number if rows in first array is 6 where as in second array it is 5.
My goal is to create a numpy matrix or array from the above list such as.
[-3., 3., 3.]
[-3., 3., 3.]
[-3., 3., 3.]
[ 1., 4., 2.]
[-0., 4., -5.]
[ 3., 6., -5.]
[-1., 2., -3.]
[-1., 2., -3.]
[-1., 2., -3.]
[-2., 2., 1.]
[-0., 4., -0.]
Is there any fast an efficient way to do so in python? I have 1000s of these array which I need to convert.
You need np.ravel the list before np.vstack:
as in your sample:
l =[[np.array([[-3., 3., 3.],
[-3., 3., 3.],
[-3., 3., 3.],
[ 1., 4., 2.],
[-0., 4., -5.],
[ 3., 6., -5.]])],
[np.array([[-1., 2., -3.],
[-1., 2., -3.],
[-1., 2., -3.],
[-2., 2., 1.],
[-0., 4., -0.],
])]]
np.vstack(np.ravel(l))
Out[119]:
array([[-3., 3., 3.],
[-3., 3., 3.],
[-3., 3., 3.],
[ 1., 4., 2.],
[-0., 4., -5.],
[ 3., 6., -5.],
[-1., 2., -3.],
[-1., 2., -3.],
[-1., 2., -3.],
[-2., 2., 1.],
[-0., 4., -0.]])
You can use zip or itertools.chain.from_iterable to "unpack" the arrays and then concatenate:
>>> np.concatenate(next(zip(*l)),axis=0)
or
>>> from itertools import chain
>>> np.concatenate([*chain.from_iterable(l)],axis=0)
output in either case
array([[-3., 3., 3.],
[-3., 3., 3.],
[-3., 3., 3.],
[ 1., 4., 2.],
[-0., 4., -5.],
[ 3., 6., -5.],
[-1., 2., -3.],
[-1., 2., -3.],
[-1., 2., -3.],
[-2., 2., 1.],
[-0., 4., -0.]])
Both are fast:
>>> timeit(lambda:np.concatenate(next(zip(*l)),axis=0))
1.8132231349591166
>>> timeit(lambda:np.concatenate([*chain.from_iterable(l)],axis=0))
1.730023997137323
>>> timeit(lambda:np.vstack(np.ravel(l)))
7.647858377080411

Python - Concatenation in an array of redondant values

I would like to "concatenate" results of detections of
positions of specific values in my array "Coord3".
I have a double criteria on my array for 2 specific dimension of it.
I get some redondant positions and i would like to gather it in order to apply a mask
of this values.
As example with a moderate array :
import numpy as np
Coord3 = np.array([[[[ 0., 0.],
[ 0., 1.],
[ 0., 2.]],
[[ 1., 0.],
[ 1., 1.],
[ 1., 2.]],
[[ 2., 0.],
[ 2., 1.],
[ 2., 2.]]],
[[[ 1., 0.],
[ 1., 1.],
[ 1., 2.]],
[[ 2., 0.],
[ 2., 1.],
[ 2., 2.]],
[[ 4., 0.],
[ 3., 1.],
[ 4., 2.]]],
[[[ 2., 0.],
[ 2., 1.],
[ 2., 2.]],
[[ 3., 0.],
[ 3., 1.],
[ 3., 2.]],
[[ 4., 0.],
[ 4., 1.],
[ 4., 4.]]]])
#I apply my double criteria in 2 shapes of my array Coord3
plaY=[]
for i in range(Coord3.shape[0]):
holding_list = zip(*np.where(Coord3[i,:,:,0] > 3))
plaY.append(holding_list)
plaY_array = np.asarray(plaY)
#plaY_array
#Out[1088]: array([[], [(2, 0), (2, 2)], [(2, 0), (2, 1), (2, 2)]], dtype=object)
plaX=[]
for i in range(Coord3.shape[0]):
holding_list = zip(*np.where(Coord3[i,:,:,1] > 2))
plaX.append(holding_list)
plaX_array = np.asarray(plaX)
#plaX_array
#Out[1097]: array([[], [], [(2, 2)]], dtype=object)
So (2,0) and (2,2) are redondant and i would like to supress it and to gather all in an unique array... as :
np.array([[2, 0], [2, 2],....])
--- EDIT LATER ------------------------------------------
I could concatenate for each specific time
plaY_array = plaY_array[:,np.newaxis]
plaX_array = plaX_array[:,np.newaxis]
test = plaX_array + plaY_array
#I get that :
#test
#array([[[[]]],
#[[[(2, 0), (2, 2)]]],
#[[[(2, 0), (2, 1), (2, 2), (2, 2)]]]], dtype=object)
So now i have to suppress just the (2,2) redondant in the "third slice", it could be interesting to know the coordinates for each specific time (so i let the (2,2) in "2nd slice"
You could turn the list of coordinates into a set to remove duplicates:
In [21]: set(zip(*(np.where(Coord3[:,:,:,0] > 3)[1:])))
Out[21]: {(2, 0), (2, 1), (2, 2)}
plaY_array = np.array(list(set(zip(*(np.where(Coord3[:,:,:,0] > 3)[1:])))))
plaX_array = np.array(list(set(zip(*(np.where(Coord3[:,:,:,1] > 2)[1:])))))
print(plaY_array)
# [[2 0]
# [2 1]
# [2 2]]
print(plaX_array)
# [[2 2]]
Also note that you can eliminate the for-loop
for i in range(Coord3.shape[0]):
by calling np.where(Coord3[:,:,:,0] > 3) instead of np.where(Coord3[i,:,:,0] > 3)
for each i:
In [16]: np.where(Coord3[:,:,:,0] > 3)
Out[16]: (array([1, 1, 2, 2, 2]), array([2, 2, 2, 2, 2]), array([0, 2, 0, 1, 2]))
The i values are in the first array, but since you don't care about those, you can just drop the first array.

plot selected rows of numpy array

Consider a small numpy array:
array([[ 0., 1., 0., 1., 0., 0., 0., 0., 0., 1.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 18., 15., 25., 0., 0., 0.],
[ 0., 0., 0., 23., 19., 20., 20., 0., 0., 0.],
[ 0., 0., 20., 22., 26., 23., 18., 0., 0., 0.],
[ 0., 0., 0., 23., 16., 20., 13., 0., 0., 0.],
[ 0., 0., 0., 0., 18., 20., 18., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 1., 0., 0., 1., 0., 0., 0., 0., 0.]])
I would like to plot, let say from the row number 3 to the row number 6, i.e. a section of my numpy array(I am coming from matlab backgroud). How could I loop this? or How could I plot multiple rows of my numpy array in the same graph?
So far I have tried; I define an arbitrary x:
x = np.arange(0,10)
then If I use
plt.plot(x,data[3,:])
to plot the third row and It does fine. The problem arises if I try:
plt.plot(x,data[3:4,:])
I get the error "x and y must have same first dimension", which I understand because he stacks row number 3 and row number 4 together, so that x and y do not have the same dimension. How can I overcome that?
Thank you
As the error implies, your data.shape = (1,10) is inconsistent with your input x.shape = (10,). To solve this problem you can just transpose your data using .T, i.e.
plt.plot(x, data[3:4,:].T)
Also, keep in mind that data[3:4,:] is the same as data[3,:], you will need to use data[3:5,:] to get the 3rd and 4th rows, for example.
Just a better application of psuedocubi's answer.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,10,10)
y = np.array(YOUR DATA HERE)
plt.plot(x,a[3:4].T,'r--',label="x vs y1") #CONTAINS YOUR 3RD ROW
plt.plot(x,a[4:5].T,'g--',label="x vs y2") #CONTAINS YOUR 4TH ROW
plt.plot(x,a[5:6].T,'b--',label="x vs y3") #CONTAINS YOUR 5TH ROW
plt.legend(loc='best')
plt.xlabel("x")
plt.ylabel("y")
plt.show()
The x here as been plotted with your own data!
You can try:
for i in range(3):
plt.plot( x , data[ i , : ] )
plt.show()
If you want a range of rows ,for example from 3 to 6 , you can use:
range(3,7,1) , where 1 is the step , 3 is the starting row and 7 is the last row we want to plot (6 ) plus one

in NumPy, how to insert an array into another array

For example, if I have a NumPy array
import numpy as np
a = np.arange(10)
b = np.zeros(5)
How can I insert b to the beginning of a?
I know I can make a new array of size len(a)+len(b) and do slice assignment, but is there a way to directly insert the array?
How about this:
c = np.hstack([b, a])
You can use numpy.concatenate:
>>> np.concatenate((b, a))
array([ 0., 0., 0., 0., 0., 0., 1., 2., 3., 4., 5., 6., 7.,
8., 9.])

Resources