Create one-dimensional arrays of arrays in numpy - python

As part of my current project I am using a third party package that at one point expects an array of shape (n,) which contains n arrays of shape (m_n,2). This array is created from a list of arrays using np.array(). Most of the time the subarrays can be expected not to have the same shape across all of them. This results in the desired output. Sometimes, however all subarrays have the same shape. Then np.array() returns an output of shape (n,m_n,2). Is there a way to force numpy to give me an output of shape (n,)? Alternatively, I'd be very thankful for a way to directly create an array like this.
Below is an example of my problem.
import numpy as np
a = np.zeros((3,2))
b = np.zeros((4,2))
list1 = [a, a]
list2 = [a, b]
array1 = np.array(list1)
array2 = np.array(list2)
print(np.shape(array1))
print(np.shape(array2))

Related

creating a multi-dimensional numpy array where each dimension of the array is of length L

I'm looking to create a numpy array of d dimensions, where each dimension is of length n.
For example:
np.zeros((5,2)), will give me a 5-row, 2-column array of zeros. What I'm looking for is a 5x5 array. Now I know I can simply do np.zeros((5,5)), but my goal is to generate the array dynamically:
dims = 4
elem_length = 10
#generate the array
#results in a 10x10x10x10 numpy array
Another option is to create single-dimensional tuples and join them all:
shp = ()
for i in range(dims):
shp = shp + (elem_length,)
new_arr = np.zeros(shp)
But that's not python-y at all. Is there a better way?
I'm not sure about numpy way to generate a dxdxdx... array, but if you wanted to generate the shape tuple you could try list comprehension.
EX:
shape_list = [elem_length for _ in range(dims)]
shape_tuple = tuple(shape_list)
print(shape_tuple)
>> (elem_length, elem_length, elem_length)
dn_arr = np.zeros(shape_tuple)
print(dn_arr.shape)
>> (elem_length, elem_length, elem_length)

Vstack of two arrays with same number of rows gives an error

I have a numpy array of shape (29, 10) and a list of 29 elements and I want to end up with an array of shape (29,11)
I am basically converting the list to a numpy array and trying to vstack, but it complain about dimensions not being the same.
Toy example
a = np.zeros((29,10))
a.shape
(29,10)
b = np.array(['A']*29)
b.shape
(29,)
np.vstack((a, b))
ValueError: all the input array dimensions except for the concatenation axis must match exactly
Dimensions do actually match, why am I getting this error and how can I solve it?
I think you are looking for np.hstack.
np.hstack((a, b.reshape(-1,1)))
Moreover b must be 2-dimensional, that's why I used a reshape.
The problem is that you want to append a 1D array to a 2D array.
Also, for the dimension you've given for b, you are probably looking for hstack.
Try this:
a = np.zeros((29,10))
a.shape
(29,10)
b = np.array(['A']*29)[:,None] #to ensure 2D structure
b.shape
(29,1)
np.hstack((a, b))
If you do want to vertically stack, you'd need this:
a = np.zeros((29,10))
a.shape
(29,10)
b = np.array(['A']*10)[None,:] #to ensure 2D structure
b.shape
(1,10)
np.vstack((a, b))

Combining list of 2D numpy arrays

How do I combine N, 2D numpy arrays (of dimension R x C) to create a 3D numpy array of shape (N, R, C)? Right now, the N-2D numpy arrays are contained inside a list, and I want that to become a 3D numpy array. Let's say X is my list of 2D numpy arrays, if I just do np.array(X), I get something of shape (N,). If I do np.vstack(X), I get something of shape (N x R, C). How do I solve this problem?
You can use np.stack:
test = np.stack([np.ones([2, 3]) for _ in range(4)])
print(test.shape) # (4, 2, 3)
you could just use :
np.array([np.array(x) for x in ArrayList])

how to convert list of different shape of arrays to numpy array in Python

I have a different shape of 3D matrices. Such as:
Matrix shape = [5,10,2048]
Matrix shape = [5,6,2048]
Matrix shape = [5,1,2048]
and so on....
I would like to put them into big matrix, but I am normally getting a shape error (since they have different shape) when I am trying to use numpy.asarray(list_of_matrix) function.
What would be your recommendation to handle such a case?
My implementation was like the following:
matrices = []
matrices.append(mat1)
matrices.append(mat2)
matrices.append(mat3)
result_matrix = numpy.asarray(matrices)
and having shape error!!
UPDATE
I am willing to have a result matrix that is 4D.
Thank you.
I'm not entirely certain if this would work for you, but it looks as though your matrices only disagree along the 1st axis, so why not concatenate them:
e.g.
>>> import numpy as np
>>> c=np.zeros((5,10,2048))
>>> d=np.zeros((5,6,2048))
>>> e=np.zeros((5,1,2048))
>>> f=np.concatenate((c,d,e),axis=1)
>>> f.shape
(5, 17, 2048)
Now, you'd have to keep track of which indices of the 1st axis corresponds to which matrices, but maybe this could work for you?

Python: Functions of arrays that return arrays of the same shape

Note: I'm using numpy
import numpy as np
Given 4 arrays of the same (but arbitrary) shape, I am trying to write a function that forms 2x2 matrices from each corresponding element of the arrays, finds the eigenvalues, and returns two arrays of the same shape as the original four, with its elements being eigenvalues (i.e. the resulting arrays would have the same shape as the input, with array1 holding all the first eigenvalues and array2 holding all the second eigenvalues).
I tried doing the following, but unsurprisingly, it gives me an error that says the array is not square.
temp = np.linalg.eig([[m1, m2],[m3, m4]])[0]
I suppose I can make an empty temp variable in the same shape,
temp = np.zeros_like(m1)
and go over each element of the original arrays and repeat the process. My problem is that I want this generalised for arrays of any arbitrary shape (need not be one dimensional). I would guess that finding the shape of the arrays and designing loops to go over each element would not be a very good way of doing it. How do I do this efficiently?
Construct a 2x2x... array:
temp = np.array([[m1, m2], [m3, m4]])
Move the first two dimensions to the end for a ...x2x2 array:
for _ in range(2):
temp = np.rollaxis(temp, 0, temp.ndim)
Call np.linalg.eigvals (which broadcasts) for a ...x2 array of eigenvalues:
eigvals = np.linalg.eigvals(temp)
And split this into an array of first eigenvalues and an array of second eigenvalues:
eigvals1, eigvals2 = eigvals[..., 0], eigvals[..., 1]

Categories