How to stack numpy array with different shape [duplicate] - python

This question already has answers here:
How to make a multidimension numpy array with a varying row size?
(7 answers)
Closed 1 year ago.
I want to stack arrays with this code.
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([7, 8])
np.stack((a, b), axis=-1)
But it returns
ValueError: all input arrays must have the same shape error.
I expect the output to be:
array([[[1, 2, 3], 7],
[[4, 5, 6], 8]])

I don't think that's a valid numpy array. You could probably do this by letting the array's dtype be an object (which could be anything, including a ragged sequence, such as yours).
data = [[[1, 2, 3], 7], [[4, 5, 6], 8]]
ar = np.array(data, dtype=object)
To build data, you can do:
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([7, 8])
data = [[_a, _b] for _a, _b in zip(a, b)]

Related

NumPy using the reshape function to reshape an array [duplicate]

This question already has an answer here:
how to reshape an N length vector to a 3x(N/3) matrix in numpy using reshape
(1 answer)
Closed 2 years ago.
I have an array: [1, 2, 3, 4, 5, 6]. I would like to use the numpy.reshape() function so that I end up with this array:
[[1, 4],
[2, 5],
[3, 6]
]
I'm not sure how to do this. I keep ending up with this, which is not what I want:
[[1, 2],
[3, 4],
[5, 6]
]
These do the same thing:
In [57]: np.reshape([1,2,3,4,5,6], (3,2), order='F')
Out[57]:
array([[1, 4],
[2, 5],
[3, 6]])
In [58]: np.reshape([1,2,3,4,5,6], (2,3)).T
Out[58]:
array([[1, 4],
[2, 5],
[3, 6]])
Normally values are 'read' across the rows in Python/numpy. This is call row-major or 'C' order. Read down is 'F', for FORTRAN, and is common in MATLAB, which has Fortran roots.
If you take the 'F' order, make a new copy and string it out, you'll get a different order:
In [59]: np.reshape([1,2,3,4,5,6], (3,2), order='F').copy().ravel()
Out[59]: array([1, 4, 2, 5, 3, 6])
You can set the order in np.reshape, in your case you can use 'F'. See docs for details
>>> arr
array([1, 2, 3, 4, 5, 6])
>>> arr.reshape(-1, 2, order = 'F')
array([[1, 4],
[2, 5],
[3, 6]])
The reason that you are getting that particular result is that arrays are normally allocates in C order. That means that reshaping by itself is not sufficient. You have to tell numpy to change the order of the axes when it steps along the array. Any number of operations will allow you to do that:
Set the axis order to F. F is for Fortran, which, like MATLAB, conventionally uses column-major order:
a.reshape(2, 3, order='F')
Swap the axes after reshaping:
np.swapaxes(a.reshape(2, 3), 0, 1)
Transpose the result:
a.reshape(2, 3).T
Roll the second axis forward:
np.rollaxis(a.reshape(2, 3), 1)
Notice that all but the first case require you to reshape to the transpose.
You can even manually arrange the data
np.stack((a[:3], a[3:]), axis=1)
Note that this will make many unnecessary copies. If you want the data copied, just do
a.reshape(2, 3, order='F').copy()

How to slice a multi-dimensional array with another multi-dimensional array? [duplicate]

This question already has answers here:
Indexing one array by another in numpy
(4 answers)
Closed 3 years ago.
I have, say, a 2D-array:
x = np.array([[4, 5, 6],
[7, 8, 9]])
and another one with indexes:
a = np.array([[0, 1],
[1, 2]])
How do I slice each row of x using the indexes in each respective row in a without using a loop in order to obtain:
[[4, 5]
[8, 9]]
Try this :
import numpy as np
x = np.array([[4, 5, 6],
[7, 8, 9]])
a = np.array([[0, 1],
[1, 2]])
print(np.take_along_axis(x,a,1))
You can use numpy.take_along_axis
np.take_along_axis(x,a,1)
# array([[4, 5],
# [8, 9]])
or manually add the first coordinate (broadcasting applies)
x[np.c_[:2],a]
# array([[4, 5],
# [8, 9]])
I know it is technically a loop, but you can do it in one line with a list comprehension.
print(np.array([x[i][a[i]] for i in range(0, x.shape[0])]))

Numpy Search & Slice 3D Array

I'm very new to Python & Numpy and am trying to accomplish the following:
Given, 3D Array:
arr_3d = [[[1,2,3],[4,5,6],[0,0,0],[0,0,0]],
[[3,2,1],[0,0,0],[0,0,0],[0,0,0]]
[[1,2,3],[4,5,6],[7,8,9],[0,0,0]]]
arr_3d = np.array(arr_3d)
Get the indices where [0,0,0] appears in the given 3D array.
Slice the given 3D array from where [0,0,0] appears first.
In other words, I'm trying to remove the padding (In this case: [0,0,0]) from the given 3D array.
Here is what I have tried,
arr_zero = np.zeros(3)
for index in range(0, len(arr_3d)):
rows, cols = np.where(arr_3d[index] == arr_zero)
arr_3d[index] = np.array(arr_3d[0][:rows[0]])
But doing this, I keep getting the following error:
Could not broadcast input array from shape ... into shape ...
I'm expecting something like this:
[[[1,2,3],[4,5,6]],
[[3,2,1]]
[[1,2,3],[4,5,6],[7,8,9]]]
Any help would be appreciated.
Get the first occurance of those indices with all() reduction alongwith argmax() and then slice each 2D slice off the 3D array -
In [106]: idx = (arr_3d == [0,0,0]).all(-1).argmax(-1)
# Output as list of arrays
In [107]: [a[:i] for a,i in zip(arr_3d,idx)]
Out[107]:
[array([[1, 2, 3],
[4, 5, 6]]), array([[3, 2, 1]]), array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])]
# Output as list of lists
In [108]: [a[:i].tolist() for a,i in zip(arr_3d,idx)]
Out[108]: [[[1, 2, 3], [4, 5, 6]], [[3, 2, 1]], [[1, 2, 3], [4, 5, 6], [7, 8, 9]]]

Numpy.split with overlapping matrixes? [duplicate]

This question already has an answer here:
How to split a numpy array in fixed size chunks with and without overlap?
(1 answer)
Closed 5 years ago.
Is it possible to use numpy.split to split a numpy.ndarray with overlapping pieces.
Example:
Given a numpy.ndarray of shape (3,3) and I want to split it into ndarray, of shape (1,1) which by
numpy.split((3,3),(1,1)) = [(1,1),(1,1),(1,1)]
But what if i wanted numpy.ndarrays of shape (3,2) , would it be able to generate a list with length 2 with overlapping numpy.ndarrays?
as such:
enter image description here
I am not exactly sure what you want to see, but this might answer your question:
With input:
> arr = np.arange(9, dtype='int64').reshape((3, 3))
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
> np.lib.index_tricks.as_strided(arr, (2, 2, 2, 2), (24, 8, 24, 8), True)
array([[[[0, 1],
[3, 4]],
[[1, 2],
[4, 5]]],
[[[3, 4],
[6, 7]],
[[4, 5],
[7, 8]]]])
Interestingly, there are no copies of the data here. Note that the values to as_strided are only accurate for 8-byte values and a 3x3 input. You could get them from the existing shape/strides of the input.

Oversample Numpy Array (2D) [duplicate]

This question already has answers here:
Quick way to upsample numpy array by nearest neighbor tiling [duplicate]
(3 answers)
Closed 7 years ago.
Is there a function in numpy/scipy to over-sample a 2D numpy array?
example:
>>> x = [[1,2]
[3,4]]
>>>
>>> y = oversample(x, (2, 3))
would returns
y = [[1,1,2,2],
[1,1,2,2],
[1,1,2,2],
[3,3,4,4],
[3,3,4,4],
[3,3,4,4]]
At the moment I've implemented my own function:
index_x = np.arange(newdim) / olddim
index_y = np.arange(newdim) / olddim
xx, yy = np.meshgrid(index_x, index_y)
return x[yy, xx, ...]
but it doesn't look like the best way as it only works for 2D reshaping as well as being a bit slow...
Any suggestions?
Thank you very much
EDIT Didnt see the comment until after post, delete if needed
Original
check np.repeat to repeat patterns. shown verbosely
>>> import numpy as np
>>> a = np.array([[1,2],[3,4]])
>>> a
array([[1, 2],
[3, 4]])
>>> b=a.repeat(3,axis=0)
>>> b
array([[1, 2],
[1, 2],
[1, 2],
[3, 4],
[3, 4],
[3, 4]])
>>> c = b.repeat(2,axis=1)
>>> c
array([[1, 1, 2, 2],
[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4],
[3, 3, 4, 4]])

Categories