Numpy: Reshape array along a specified axis - python

I have the following array:
x = np.arange(24).reshape((2,3,2,2))
array([[[[ 0, 1],
[ 2, 3]],
[[ 4, 5],
[ 6, 7]],
[[ 8, 9],
[10, 11]]],
[[[12, 13],
[14, 15]],
[[16, 17],
[18, 19]],
[[20, 21],
[22, 23]]]])
I would like to reshape it to a (3,4,2) array like below:
array([[[ 0, 1],
[ 2, 3],
[12, 13],
[14, 15]],
[[ 4, 5],
[ 6, 7],
[16, 17],
[18, 19]],
[[ 8, 9],
[10, 11],
[20, 21],
[22, 23]]])
I've tried to use reshape but it gave me the following which is not what I want.
array([[[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7]],
[[ 8, 9],
[10, 11],
[12, 13],
[14, 15]],
[[16, 17],
[18, 19],
[20, 21],
[22, 23]]])
Can someone please help?

Use transpose and then reshape like so -
shp = x.shape
out = x.transpose(1,0,2,3).reshape(shp[1],-1,shp[-1])

x = np.arange(24).reshape((2,3,2,2))
y = np.dstack(zip(x))[0]
print y
result:
[[[ 0 1]
[ 2 3]
[12 13]
[14 15]]
[[ 4 5]
[ 6 7]
[16 17]
[18 19]]
[[ 8 9]
[10 11]
[20 21]
[22 23]]]

You can also use concatenate like so-
out=np.concatenate((x),axis=1)
I will note those since you mentioned this is for performance, this doesn't seem faster than Divakar suggestion:
shp = x.shape
out = x.transpose(1,0,2,3).reshape(shp[1],-1,shp[-1])
If anyone does a bench mark or finds something faster I would love to know.

Related

An easy way to create a torch tensor from multiple elements of tuple through concatenate

Inputs
I have list as follow
r1 = [([[[1, 2, 3], [1, 2, 3]],
[[4, 5, 6], [4, 5, 6]]],
[[[7, 8], [7, 8]],
[[9, 10], [9, 10]]]),
([[[11, 12, 13], [11, 12, 13]],
[[14, 15, 16], [14, 15, 16]]],
[[[17, 18], [17, 18]],
[[19, 20], [19, 20]]])]
I'm going to make 2 torch tensors from the input above.
my desired output is as follow
output
output =
[tensor([[[ 1, 2, 3],
[ 1, 2, 3]],
[[ 4, 5, 6],
[ 4, 5, 6]],
[[11, 12, 13],
[11, 12, 13]],
[[14, 15, 16],
[14, 15, 16]]]),
tensor([[[ 7, 8],
[ 7, 8]],
[[ 9, 10],
[ 9, 10]],
[[17, 18],
[17, 18]],
[[19, 20],
[19, 20]]])]
My code is as follows.
output = []
for i in range(len(r1[0])):
templates = []
for j in range(len(r1)):
templates.append(torch.tensor(r1[j][i]))
template = torch.cat(templates)
output.append(template)
Is there a simpler or easier way to get the result I want?
This will do:
output = [torch.Tensor([*a, *b]) for a, b in zip(*r1)]
It concatenates the corresponding items of the two list first then create the Tensor

Python numpy function for matrix math

I have to np arrays
a = np.array[[1,2]
[2,3]
[3,4]
[5,6]]
b = np.array [[2,4]
[6,8]
[10,11]
I want to multiple each row of a against each element in array b so that array c is created with dimensions of a-rows x b rows (as columns)
c = np.array[[2,8],[6,16],[10,22]
[4,12],[12,21],[20,33]
....]
There are other options for doing this, but I would really like to leverage the speed of numpy's ufuncs...if possible.
any and all help is appreciated.
Does this do what you want?
>>> a
array([[1, 2],
[2, 3],
[3, 4],
[5, 6]])
>>> b
array([[ 2, 4],
[ 6, 8],
[10, 11]])
>>> a[:,None,:]*b
array([[[ 2, 8],
[ 6, 16],
[10, 22]],
[[ 4, 12],
[12, 24],
[20, 33]],
[[ 6, 16],
[18, 32],
[30, 44]],
[[10, 24],
[30, 48],
[50, 66]]])
>>> _.shape
(4, 3, 2)
Or if that doesn't have the right shape, you can reshape it:
>>> (a[:,None,:]*b).reshape((a.shape[0]*b.shape[0], 2))
array([[ 2, 8],
[ 6, 16],
[10, 22],
[ 4, 12],
[12, 24],
[20, 33],
[ 6, 16],
[18, 32],
[30, 44],
[10, 24],
[30, 48],
[50, 66]])

How to slice multidimensional array with Numpy, multiple columns?

I am generating multidimensional array of different sizes, though they'll all have an even number of columns.
>> import numpy as np
>> x = np.arange(24).reshape((3,8))
Which results in:
array([[ 0, 1, 2, 3, 4, 5, 6, 7],
[ 8, 9, 10, 11, 12, 13, 14, 15],
[16, 17, 18, 19, 20, 21, 22, 23]])
I am able to slice with numpy and get the first column in an array:
>> newarr = x[0:,0:2]
array([[ 0, 1],
[ 8, 9],
[16, 17]])
However, I want to have one array that is just a list of the columns where column 1 and 2 are together, 3 and 4 are together, and so on.. For example:
array([[[ 0, 1],
[ 8, 9],
[16, 17]],
[[ 2, 3],
[10, 11],
[18, 19]],
etc....]
)
This code below works but it's clunky and my arrays are not all the same. Some arrays have 16 columns, some have 34, some have 50, etc.
>> newarr = [x[0:,0:2]]+[x[0:,2:4]]+[x[0:,4:6]]
[array([[ 0, 1],
[ 8, 9],
[16, 17]]), array([[ 2, 3],
[10, 11],
[18, 19]])]
There's got to be a better way to do this than
newarr = [x[0:,0:2]]+[x[0:,2:4]]+[x[0:,4:6]]+...+[x[0:,n:n+2]]
Help!
My idea is adding a for loop:
slice_len = 2
x_list = [x[0:, slice_len*i:slice_len*(i+1)] for i in range(x.shape[1] // slice_len)]
Output:
[array([[ 0, 1],
[ 8, 9],
[16, 17]]), array([[ 2, 3],
[10, 11],
[18, 19]]), array([[ 4, 5],
[12, 13],
[20, 21]]), array([[ 6, 7],
[14, 15],
[22, 23]])]

Is not it possible to patch the 2d array into array of subarry using functions available in numpy?

Is not it possible to patch the 2d array into array of subarry using np.reshape and np.split functions?
import numpy as np
data = np.arange(24).reshape(4,6)
print data
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
answer = np.split(data,(-1,2,2),axis=1)
Expected answer is:
answer = [[[ 0 1]
[ 6 7]]
[[ 2 3]
[ 8 9]]
[[ 4 5]
[10 11]]
[[12 13]
[18 19]]
[[14 15]
[20 21]]
[[16 17]
[22 23]]]
split can't be used with multiple axis at once. But here is a solution using this operation twice:
In [1]: import numpy as np
In [2]: data = np.arange(24).reshape(4,6)
In [3]: chunk = 2, 2
In [4]: tmp = np.array(np.split(data, data.shape[1]/chunk[1], axis=1))
In [5]: answer = np.vstack(np.split(tmp, tmp.shape[1]/chunk[0], axis=1))
In [6]: answer
Out[6]:
array([[[ 0, 1],
[ 6, 7]],
[[ 2, 3],
[ 8, 9]],
[[ 4, 5],
[10, 11]],
[[12, 13],
[18, 19]],
[[14, 15],
[20, 21]],
[[16, 17],
[22, 23]]])
However I prefer the blockshaped solution as noticed by Cyber.
You could also do the following:
>>> data = np.arange(24).reshape(4,6)
>>> data_split = data.reshape(2, 2, 3, 2)
>>> data_split = np.transpose(data_split, (0, 2, 1, 3))
>>> data_split = data_split.reshape(-1, 2, 2) # this makes a copy
>>> data_split
array([[[ 0, 1],
[ 6, 7]],
[[ 2, 3],
[ 8, 9]],
[[ 4, 5],
[10, 11]],
[[12, 13],
[18, 19]],
[[14, 15],
[20, 21]],
[[16, 17],
[22, 23]]])
If you really want to call split on this array, it should be pretty straightforward to do, but this reordered array will behave as the tuple returned by split in most settings.

Transposing arrays in an array

I have a 2D array of shape (M*N,N) which in fact consists of M, N*N arrays. I would like to transpose all of these elements(N*N matrices) in a vectorized fashion. As an example,
import numpy as np
A=np.arange(1,28).reshape((9,3))
print "A before transposing:\n", A
for i in range(3):
A[i*3:(i+1)*3,:]=A[i*3:(i+1)*3,:].T
print "A after transposing:\n", A
This code generates the following output:
A before transposing:
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]
[13 14 15]
[16 17 18]
[19 20 21]
[22 23 24]
[25 26 27]]
A after transposing:
[[ 1 4 7]
[ 2 5 8]
[ 3 6 9]
[10 13 16]
[11 14 17]
[12 15 18]
[19 22 25]
[20 23 26]
[21 24 27]]
Which I expect. But I want the vectorized version.
Here's a nasty way to do it in one line!
A.reshape((-1, 3, 3)).swapaxes(-1, 1).reshape(A.shape)
Step by step. Reshape to (3, 3, 3)
>>> A.reshape((-1, 3, 3))
array([[[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9]],
[[10, 11, 12],
[13, 14, 15],
[16, 17, 18]],
[[19, 20, 21],
[22, 23, 24],
[25, 26, 27]]])
Then perform a transpose-like operation swapaxes on each sub-array
>>> A.reshape((-1, 3, 3)).swapaxes(-1, 1)
array([[[ 1, 4, 7],
[ 2, 5, 8],
[ 3, 6, 9]],
[[10, 13, 16],
[11, 14, 17],
[12, 15, 18]],
[[19, 22, 25],
[20, 23, 26],
[21, 24, 27]]])
Finally reshape to (9, 3).
>>> A.reshape((-1, 3, 3)).swapaxes(-1, 1).reshape(A.shape)
array([[ 1, 4, 7],
[ 2, 5, 8],
[ 3, 6, 9],
[10, 13, 16],
[11, 14, 17],
[12, 15, 18],
[19, 22, 25],
[20, 23, 26],
[21, 24, 27]])
>>>
I think that with any method, data must be copied since there's no 2d strides/shape that can generate the result from:
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27])
(is there?) In my version I think data is copied in the final reshape step
In [42]: x = np.arange(1,28).reshape((9,3))
In [43]: x
Out[43]:
array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12],
[13, 14, 15],
[16, 17, 18],
[19, 20, 21],
[22, 23, 24],
[25, 26, 27]])
In [31]: r,c = x.shape
In [39]: z = np.vstack(np.hsplit(x.T,r/c))
In [45]: z
Out[45]:
array([[ 1, 4, 7],
[ 2, 5, 8],
[ 3, 6, 9],
[10, 13, 16],
[11, 14, 17],
[12, 15, 18],
[19, 22, 25],
[20, 23, 26],
[21, 24, 27]])

Categories

Resources