Related
For example array x, np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
Divided into 3 "folds" along axis-0 would be like [array([[1, 2, 3, 4]]), array([[5, 6, 7, 8]]), array([[ 9, 10, 11, 12]] in a list.
In [1]: import numpy as np
In [2]: a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
In [3]: np.array_split(a, 3)
Out[3]: [array([[1, 2, 3, 4]]), array([[5, 6, 7, 8]]), array([[ 9, 10, 11, 12]])]
axis=0 is the default, you can specify another axis as well
In [4]: np.array_split(a, 4, axis=1)
Out[4]:
[array([[1],
[5],
[9]]), array([[ 2],
[ 6],
[10]]), array([[ 3],
[ 7],
[11]]), array([[ 4],
[ 8],
[12]])]
I want a numpy array like this:
b = np.array([[1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3],
[4, 4, 4, 4, 4, 4],
[5, 5, 5, 5, 5, 5],
[6, 6, 6, 6, 6, 6],
[7, 7, 7, 7, 7, 7],
[8, 8, 8, 8, 8, 8],
[9, 9, 9, 9, 9, 9]])
Is there a faster way to create a NumPy array like this instead of typing them manually?
You can do something like this:
>>> np.repeat(np.arange(1, 10).reshape(-1,1), 6, axis=1)
array([[1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3],
[4, 4, 4, 4, 4, 4],
[5, 5, 5, 5, 5, 5],
[6, 6, 6, 6, 6, 6],
[7, 7, 7, 7, 7, 7],
[8, 8, 8, 8, 8, 8],
[9, 9, 9, 9, 9, 9]])
Explanation:
np.arange(1, 10).reshape(-1,1) creates an array
array([[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9]])
np.repeat(_, 6, axis=1) repeats this 6 times on the first (or second in human words) axis.
Yes. There are plenty of methods. This is one:
np.repeat(np.arange(1,10),6,axis=0).reshape(9,6)
Another method is to use broadcasting:
>>> np.arange(1,10)[:,None] * np.ones(6, dtype=int)
array([[1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3],
[4, 4, 4, 4, 4, 4],
[5, 5, 5, 5, 5, 5],
[6, 6, 6, 6, 6, 6],
[7, 7, 7, 7, 7, 7],
[8, 8, 8, 8, 8, 8],
[9, 9, 9, 9, 9, 9]])
For any w*l size, convert a list of lists into an np.array like so:
w = 6
l = 9
[np.array([[1+i]*w for i in range(d)])
array([[1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3],
[4, 4, 4, 4, 4, 4],
[5, 5, 5, 5, 5, 5],
[6, 6, 6, 6, 6, 6],
[7, 7, 7, 7, 7, 7],
[8, 8, 8, 8, 8, 8],
[9, 9, 9, 9, 9, 9]])
np.transpose(np.array(([np.arange(1,10)] * 6)))
np.arange(1,10) creates an numpy array from 1 to 9.
[] puts the array into a list.
*6 augments the array 6 times.
np.array() converts the resulting structure (list of arrays) to a numpy array
np.transpose() rotates the orientation of the numpy array to get vertical one.
I know that numpy.roll can shift an array along one or more existing axes. How would I create a new axis on array x along which I want to have views or copies of itself rolled by array shift?
Example:
x = np.arange(10)
shift = np.array([2, 4])
#input
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
#output
array(
[[8, 6],
[9, 7],
[0, 8],
[1, 9],
[2, 0],
[3, 1],
[4, 2],
[5, 3],
[6, 4],
[7, 5]])
Edit: I'm looking for a general solution (ideally without looping) that can also be applied on higher dimensional arrays. Another example:
x = np.arange(20).reshape(2, 10)
shift = np.array([2, 4])
#input
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])
#output
array(
[[[ 8, 6],
[ 9, 7],
[ 0, 8],
[ 1, 9],
[ 2, 0],
[ 3, 1],
[ 4, 2],
[ 5, 3],
[ 6, 4],
[ 7, 5]],
[[18, 16],
[19, 17],
[10, 18],
[11, 19],
[12, 10],
[13, 11],
[14, 12],
[15, 13],
[16, 14],
[17, 15]]])
Here's a vectorized solution leveraging broadcasting that covers generic n-dim array cases -
np.take(x,(-shift + np.arange(x.shape[-1])[:,None]),axis=-1)
Sample runs
1) x as 1D -
In [114]: x = np.arange(10)
...: shift = np.array([2, 4])
In [115]: np.take(x,(-shift + np.arange(x.shape[-1])[:,None]),axis=-1)
Out[115]:
array([[8, 6],
[9, 7],
[0, 8],
[1, 9],
[2, 0],
[3, 1],
[4, 2],
[5, 3],
[6, 4],
[7, 5]])
2) x as 2D -
In [116]: x = np.arange(20).reshape(2, 10)
...: shift = np.array([2, 4])
In [117]: np.take(x,(-shift + np.arange(x.shape[-1])[:,None]),axis=-1)
Out[117]:
array([[[ 8, 6],
[ 9, 7],
[ 0, 8],
[ 1, 9],
[ 2, 0],
[ 3, 1],
[ 4, 2],
[ 5, 3],
[ 6, 4],
[ 7, 5]],
[[18, 16],
[19, 17],
[10, 18],
[11, 19],
[12, 10],
[13, 11],
[14, 12],
[15, 13],
[16, 14],
[17, 15]]])
I almost hate to provide this alternative because I think #BenT's answer is simple and logical
np.array([np.roll(x,sh) for sh in shift]).T
np.stack([np.roll(x,sh) for sh in shift], axis=1) # may be easier to generalize
but I can do the original x=np.arange(10) case with as_strided:
Perform all shifts:
In [352]: arr = np.lib.stride_tricks.as_strided(np.hstack((x,x)),shape=(10,10), strides=(8,8))
In [353]: arr
Out[353]:
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
[2, 3, 4, 5, 6, 7, 8, 9, 0, 1],
[3, 4, 5, 6, 7, 8, 9, 0, 1, 2],
[4, 5, 6, 7, 8, 9, 0, 1, 2, 3],
[5, 6, 7, 8, 9, 0, 1, 2, 3, 4],
[6, 7, 8, 9, 0, 1, 2, 3, 4, 5],
[7, 8, 9, 0, 1, 2, 3, 4, 5, 6],
[8, 9, 0, 1, 2, 3, 4, 5, 6, 7],
[9, 0, 1, 2, 3, 4, 5, 6, 7, 8]])
Then select the ones you want:
In [358]: arr[::-1][shift-1]
Out[358]:
array([[8, 9, 0, 1, 2, 3, 4, 5, 6, 7],
[6, 7, 8, 9, 0, 1, 2, 3, 4, 5]])
I wrote and tested the stack version with one try, but had to try several things to get the as_strided right.
I'd also prefer generalizing the list comprehension to higher dimensions.
For your 2d x:
np.stack([np.roll(x,sh, axis=1) for sh in shift],2)
Consider a 2D array
>>> A = np.array(range(16)).reshape(4, 4)
>>> A
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
I would like to construct a function f(i,j) which pulls a 3x3 block from elements surrounding A[i,j] with periodic boundary conditions.
For example a non-boundary element would be
>>> f(1,1)
array([[ 0, 1, 2],
[ 4, 5, 6],
[ 8, 9, 10]])
and a boundary element would be
>>> f(0,0)
array([[15, 12, 13],
[ 3, 0, 1],
[ 7, 4, 5]])
view_as_windows comes close but does not wrap around periodic boundaries.
>>> from skimage.util.shape import view_as_windows
>>> view_as_windows(A,(3,3))
array([[[[ 0, 1, 2],
[ 4, 5, 6],
[ 8, 9, 10]],
[[ 1, 2, 3],
[ 5, 6, 7],
[ 9, 10, 11]]],
[[[ 4, 5, 6],
[ 8, 9, 10],
[12, 13, 14]],
[[ 5, 6, 7],
[ 9, 10, 11],
[13, 14, 15]]]])
In this case view_as_windows(A)[0,0] == f(1,1) but f(0,0) is not in view_as_windows(A). I need a view_as_windows(A) type array which has the same number of elements as A, where each element has shape (3,3)
Simply pad with wrapping functionality using np.pad and then use Scikit's view_as_windows -
from skimage.util.shape import view_as_windows
Apad = np.pad(A,1,'wrap')
out = view_as_windows(Apad,(3,3))
Sample run -
In [65]: A
Out[65]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
In [66]: Apad = np.pad(A,1,'wrap')
In [67]: out = view_as_windows(Apad,(3,3))
In [68]: out[0,0]
Out[68]:
array([[15, 12, 13],
[ 3, 0, 1],
[ 7, 4, 5]])
In [69]: out[1,1]
Out[69]:
array([[ 0, 1, 2],
[ 4, 5, 6],
[ 8, 9, 10]])
I have a 3d array from which I am trying to a list of stabs. Put another way, given the array:
t = np.array([[[1,2],[3,4]],[[5,6],[7,8]],[[9,10],[11,12]]])
array([[[ 1, 2],
[ 3, 4]],
[[ 5, 6],
[ 7, 8]],
[[ 9, 10],
[11, 12]]])
I am trying to retrieve:
array([[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11],
[ 4, 8, 12]])
np.ndarray.reshape seems to reorganise elements in a sequential order that precludes stabs.
numpy.lib.stride_tricks.as_strided might work, but I have yet to find the correct combination of values.
Transpose then reshape:
>>> t.transpose(1, 2, 0).reshape(4, 3)
array([[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11],
[ 4, 8, 12]])
Edit: alternatively, you can reshape then transpose:
>>> t.reshape(3, 4).T
array([[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11],
[ 4, 8, 12]])