Numpy : convert 2D array to 3D array - python

I have a 2 dimensional array : A = numpy.array([[1, 2, 3], [4, 5, 6]]) and would like to convert it to a 3 dimensional array : B = numpy.array([[[1, 2, 3], [4, 5, 6]]])
Is there a simple way to do that ?

Simply add a new axis at the start with np.newaxis -
import numpy as np
B = A[np.newaxis,:,:]
We could skip listing the trailing axes -
B = A[np.newaxis]
Also, bring in the alias None to replace np.newaxis for a more compact solution -
B = A[None]

It is also possible to create a new NumPy array by using the constructor so that it takes in a list. This list contains a single element which is the array A and it will allow you to create same array with the singleton dimension being the first one. The result would be the 3D array you desire:
B = numpy.array([A])
Example Output
In [13]: import numpy as np
In [14]: A = np.array([[1, 2, 3], [4, 5, 6]])
In [15]: B = np.array([A])
In [16]: B
Out[16]:
array([[[1, 2, 3],
[4, 5, 6]]])

Related

How to index a numpy array of dimension N with a 1-dimensional array of shape (N,)

I would like to index an array of dimension N using an array of size (N,).
For example, let us consider a case where N is 2.
import numpy as np
foo = np.arange(9).reshape(3,3)
bar = np.array((2,1))
>>> foo
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>>bar
array([2, 1])
>>>foo[bar[0],bar[1]]
7
This works fine. However, with this method, I would need to write N times bar[i], which is not a nice solution if N is high.
The following command does not give the result that I need:
>>>foo[bar]
array([[6, 7, 8],
[3, 4, 5]])
What could I do to get the result that I want in a nice and concise way?
I think you can turn bar into tuple:
foo[tuple(bar)]
# 7

How to apply a function on jagged Numpy arrays (unequal row lengths) without using np.apply_along_axis()?

I'm trying to speed up a process, I think this might be possible using numpy's apply_along_axis. The problem is that not all my axis have the same length.
When I do:
a = np.array([[1, 2, 3],
[2, 3, 4],
[4, 5, 6]])
b = np.apply_along_axis(sum, 1, a)
print(b)
This works fine. But I would like to do something similar to (please note that the first row has 4 elements and the rest have 3):
a = np.array([[1, 2, 3, 4],
[2, 3, 4],
[4, 5, 6]])
b = np.apply_along_axis(sum, 1, a)
print(b)
But this fails because:
numpy.AxisError: axis 1 is out of bounds for array of dimension 1
I've looked around and the only 'solution' I've found is to add zeros to make all the arrays the same length, which would probably defeat the purpose of performance improvement.
Is there any way to use numpy_apply_along_axis on a non-regular shaped numpy array?
You can transform your initial array of iterable-objects to ndarray by padding them with zeros in a vectorized manner:
import numpy as np
a = np.array([[1, 2, 3, 4],
[2, 3, 4],
[4, 5, 6]])
max_len = len(max(a, key = lambda x: len(x))) # max length of iterable-objects contained in array
cust_func = np.vectorize(pyfunc=lambda x: np.pad(array=x,
pad_width=(0,max_len),
mode='constant',
constant_values=(0,0))[:max_len], otypes=[list])
a_pad = np.stack(cust_func(a))
output:
array([[1, 2, 3, 4],
[2, 3, 4, 0],
[4, 5, 6, 0]])
It depends.
Do you know the size of the vectors before or are you appending to a list?
see e.g. http://stackoverflow.com/a/58085045/7919597
You could for example pad the arrays
import numpy as np
a1 = [1, 2, 3, 4]
a2 = [2, 3, 4, np.nan] # pad with nan
a3 = [4, 5, 6, np.nan] # pad with nan
b = np.stack([a1, a2, a3], axis=0)
print(b)
# you can apply the normal numpy operations on
# arrays with nan, they usually just result in a nan
# in a resulting array
c = np.diff(b, axis=-1)
print(c)
Afterwards you can apply a moving window on each row over the columns.
Have a look at https://stackoverflow.com/a/22621523/7919597 which is only 1d, but can give you an idea of how it could work.
It is possible to use a 2d array with only one row as kernel (shape e.g. (1, 3)) with scipy.signal.convolve2d and use the idea above.
This is a workaround to get a "row-wise 1D convolution":
from scipy import signal
krnl = np.array([[0, 1, 0]])
d = signal.convolve2d(c, krnl, mode='same')
print(d)

Append a 1d array to a 2d array in Numpy Python

I have a numpy 2D array [[1,2,3]].
I need to append a numpy 1D array,( say [4,5,6]) to it, so that it becomes [[1,2,3], [4,5,6]]
This is easily possible using lists, where you just call append on the 2D list.
But how do you do it in Numpy arrays?
np.concatenate and np.append dont work. they convert the array to 1D for some reason.
Thanks!
You want vstack:
In [45]: a = np.array([[1,2,3]])
In [46]: l = [4,5,6]
In [47]: np.vstack([a,l])
Out[47]:
array([[1, 2, 3],
[4, 5, 6]])
You can stack multiple rows on the condition that The arrays must have the same shape along all but the first axis.
In [53]: np.vstack([a,[[4,5,6], [7,8,9]]])
Out[53]:
array([[1, 2, 3],
[4, 5, 6],
[4, 5, 6],
[7, 8, 9]])
Try this:
np.concatenate(([a],[b]),axis=0)
when
a = np.array([1,2,3])
b = np.array([4,5,6])
then result should be:
array([[1, 2, 3],
[4, 5, 6]])

How do you unroll a Numpy array of (mxn) dimentions into a single vector

I just want to know if there is a short cut to unrolling numpy arrays into a single vector. For instance (convert the following Matlab code to python):
Matlab way:
A = zeros(10,10) %
A_unroll = A(:) % <- How can I do this in python
Thank in advance.
Is this what you have in mind?
Edit: As Patrick points out, one has to be careful with translating A(:) to Python.
Of course if you just want to flatten out a matrix or 2-D array of zeros it does not matter.
So here is a way to get behavior like matlab's.
>>> a = np.array([[1,2,3], [4,5,6]])
>>> a
array([[1, 2, 3],
[4, 5, 6]])
>>> # one way to get Matlab behaivor
... (a.T).ravel()
array([1, 4, 2, 5, 3, 6])
numpy.ravel does flatten 2D array, but does not do it the same way matlab's (:) does.
>>> import numpy as np
>>> a = np.array([[1,2,3], [4,5,6]])
>>> a
array([[1, 2, 3],
[4, 5, 6]])
>>> a.ravel()
array([1, 2, 3, 4, 5, 6])
You have to be careful here, since ravel doesn't unravel the elements in the same that Matlab does with A(:). If you use:
>>> a = np.array([[1,2,3], [4,5,6]])
>>> a.shape
(2,3)
>>> a.ravel()
array([1, 2, 3, 4, 5, 6])
While in Matlab:
>> A = [1:3;4:6];
>> size(A)
ans =
2 3
>> A(:)
ans =
1
4
2
5
3
6
In Matlab, the elements are unraveled first down the columns, then by the rows. In Python it's the opposite. This has to do with the order that elements are stored in (C order by default in NumPy vs. Fortran order in Matlab).
Knowing that A(:) is equivalent to reshape(A,[numel(A),1]), you can get the same behaviour in Python with:
>>> a.reshape(a.size,order='F')
array([1, 4, 2, 5, 3, 6])
Note order='F' which refers to Fortran order (columns first unravelling).

how to convert 2d list to 2d numpy array?

I have a 2D list something like
a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
and I want to convert it to a 2d numpy array. Can we do it without allocating memory like
numpy.zeros((3,3))
and then storing values to it?
Just pass the list to np.array:
a = np.array(a)
You can also take this opportunity to set the dtype if the default is not what you desire.
a = np.array(a, dtype=...)
just use following code
c = np.matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
matrix([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
Then it will give you
you can check shape and dimension of matrix by using following code
c.shape
c.ndim
np.array() is even more powerful than what unutbu said above.
You also could use it to convert a list of np arrays to a higher dimention array, the following is a simple example:
aArray=np.array([1,1,1])
bArray=np.array([2,2,2])
aList=[aArray, bArray]
xArray=np.array(aList)
xArray's shape is (2,3), it's a standard np array. This operation avoids a loop programming.
I am using large data sets exported to a python file in the form
XVals1 = [.........]
XVals2 = [.........]
Each list is of identical length. I use
>>> a1 = np.array(SV.XVals1)
>>> a2 = np.array(SV.XVals2)
Then
>>> A = np.matrix([a1,a2])

Categories