Related
Let's say I have an array X of shape (6, 2) like this:
import numpy as np
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
I want to reshape it to an array of shape (3, 2, 2), so I did this:
X.reshape(3, 2, 2)
And got:
array([[[ 1, 2],
[ 3, 4]],
[[ 5, 6],
[ 7, 8]],
[[ 9, 10],
[11, 12]]])
However, I need my data in a different format. To be precise, I want to end up wth:
array([[[ 1, 2],
[ 7, 8]],
[[ 3, 4],
[ 9, 10]],
[[ 5, 6],
[11, 12]]])
Should I be using reshape for this or something else? What's the best way to do this in Numpy?
You have to set the order option:
>>> X.reshape(3, 2, 2, order='F')
array([[[ 1, 2],
[ 7, 8]],
[[ 3, 4],
[ 9, 10]],
[[ 5, 6],
[11, 12]]])
‘F’ means to read / write the elements using Fortran-like index order, with the first index changing fastest, and the last index changing slowest.
see: https://numpy.org/doc/stable/reference/generated/numpy.reshape.html
You need to specify order;
X.reshape(3, 2, 2, order='F')
should work
A functional equivalent to the order='F' reshape:
In [31]: x.reshape(2,3,2).transpose(1,0,2)
Out[31]:
array([[[ 1, 2],
[ 7, 8]],
[[ 3, 4],
[ 9, 10]],
[[ 5, 6],
[11, 12]]])
In [32]: x.reshape(2,3,2).transpose(1,0,2).strides
Out[32]: (16, 48, 8)
Without the transpose the strides would be (48,16,8).
A thing that's a bit tricky about this layout is that the last dimension remains in 'C' order. It's the just first two dimension that are switched.
The full 'F' layout would be
In [33]: x = np.arange(1,13).reshape(3,2,2,order='F')
In [34]: x
Out[34]:
array([[[ 1, 7],
[ 4, 10]],
[[ 2, 8],
[ 5, 11]],
[[ 3, 9],
[ 6, 12]]])
I have a 4000 x 16 matrix A. I have 256 x 1 vector B. I need to get the elementwise addition for each element in A with every element of B and get a 3D array of size 4000 x 16 x 256. What is the most efficient way to achieve this without loops with numpy?
You can first reshape A to a 4000×16×1 matrix, and B to 1×1×256 matrix. Then you can perform addition:
A[:,:,None] + B.reshape(1, 1, -1)
For A a 4×5 matrix, and B a 3×1 matrix, for example, we get:
>>> A
array([[1, 2, 2, 2, 2],
[2, 1, 0, 3, 2],
[4, 1, 2, 1, 3],
[3, 2, 3, 2, 2]])
>>> B
array([[0],
[3],
[3],
[6],
[4],
[3]])
>>> A[:,:,None] + B.reshape(1, 1, -1)
array([[[ 1, 4, 4, 7, 5, 4],
[ 2, 5, 5, 8, 6, 5],
[ 2, 5, 5, 8, 6, 5],
[ 2, 5, 5, 8, 6, 5],
[ 2, 5, 5, 8, 6, 5]],
[[ 2, 5, 5, 8, 6, 5],
[ 1, 4, 4, 7, 5, 4],
[ 0, 3, 3, 6, 4, 3],
[ 3, 6, 6, 9, 7, 6],
[ 2, 5, 5, 8, 6, 5]],
[[ 4, 7, 7, 10, 8, 7],
[ 1, 4, 4, 7, 5, 4],
[ 2, 5, 5, 8, 6, 5],
[ 1, 4, 4, 7, 5, 4],
[ 3, 6, 6, 9, 7, 6]],
[[ 3, 6, 6, 9, 7, 6],
[ 2, 5, 5, 8, 6, 5],
[ 3, 6, 6, 9, 7, 6],
[ 2, 5, 5, 8, 6, 5],
[ 2, 5, 5, 8, 6, 5]]])
Performance: If I run the above 100 times with A a 4000×16 matrix, and B a 256×1 matrix of floating points, I get the following results:
>>> timeit(lambda: A[:,:,None] + B.reshape(1, 1, -1), number=100)
5.949456596048549
It thus takes roughly 59.49457ms for a single run. This looks reasonable to calculate 16'384'000 elements.
This is where numpy's broadcasting and np.transpose() features really shine!
A[:,:, np.newaxis] + B[np.newaxis,:,:].transpose(2,0,1)
I have a data set like this
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
How can I reshape this into shape (3,2,2) so that a[:,0,0] = [1,2,3]?
you can use two steps:
step1.
In [28]: b1 = np.reshape(a,(3,4), order='F')
In [29]: b1
Out[29]:
array([[ 1, 4, 7, 10],
[ 2, 5, 8, 11],
[ 3, 6, 9, 12]])
use order='F' means to read / write the elements using Fortran-like index order, with the first index changing fastest, and the last index changing slowest. numpy.reshape
setp2
In [30]: c = b1.reshape(3,2,2)
In [31]: c
Out[31]:
array([[[ 1, 4],
[ 7, 10]],
[[ 2, 5],
[ 8, 11]],
[[ 3, 6],
[ 9, 12]]])
get the final result:
In [34]: c[:,0,0]
Out[34]: array([1, 2, 3])
In [30]: a=np.arange(1,13)
In [31]: a
Out[31]: array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
Since you want to keep the first 3 values 'together', we could start with a reshape like:
In [32]: a.reshape(2,2,3)
Out[32]:
array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]])
and then swap a couple of the axes:
In [33]: a.reshape(2,2,3).transpose(2,0,1)
Out[33]:
array([[[ 1, 4],
[ 7, 10]],
[[ 2, 5],
[ 8, 11]],
[[ 3, 6],
[ 9, 12]]])
In [34]: _[:,0,0]
Out[34]: array([1, 2, 3])
Or with a different transpose:
In [35]: a.reshape(2,2,3).transpose(2,1,0)
Out[35]:
array([[[ 1, 7],
[ 4, 10]],
[[ 2, 8],
[ 5, 11]],
[[ 3, 9],
[ 6, 12]]])
transpose() with an argument, (also invoked with .T) does the same thing.
So your question is a bit ambiguous.
So does the reshape with order F mentioned in the other answer:
In [37]: a.reshape(3,2,2, order='F')
Out[37]:
array([[[ 1, 7],
[ 4, 10]],
[[ 2, 8],
[ 5, 11]],
[[ 3, 9],
[ 6, 12]]])
(though the two step, a.reshape(3,4, order='F').reshape(3,2,2) produces my first result Out[33]).
I have an array :
e = np.array([[ 0, 1, 2, 3, 5, 6, 7, 8],
[ 4, 5, 6, 7, 5, 3, 2, 5],
[ 8, 9, 10, 11, 4, 5, 3, 5]])
I want to extract array by its columns in RANGE, if I want to take column in range 1 until 5, It will return
e = np.array([[ 1, 2, 3, 5, ],
[ 5, 6, 7, 5, ],
[ 9, 10, 11, 4, ]])
How to solve it? Thanks
You can just use e[:, 1:5] to retrive what you want.
In [1]: import numpy as np
In [2]: e = np.array([[ 0, 1, 2, 3, 5, 6, 7, 8],
...: [ 4, 5, 6, 7, 5, 3, 2, 5],
...: [ 8, 9, 10, 11, 4, 5, 3, 5]])
In [3]: e[:, 1:5]
Out[3]:
array([[ 1, 2, 3, 5],
[ 5, 6, 7, 5],
[ 9, 10, 11, 4]])
https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
Numpy row and column indices start counting at 0.
The rows are specified first and then the column with a comma to separate the row from column.
The ":" (colon) is used to shortcut all rows or all columns when it is used alone.
When the row or column specifier has a range, then the ":" is paired with numbers that specify the inclusive start range and the exclusive end range.
For example
import numpy as np
np_array = np.array( [ [ 1, 2, 3, ],
[ 4, 5, 6, ],
[ 7, 8, 9 ] ] )
first_row = np_array[0,:]
first_row
output: array([1, 2, 3])
last_column = np_array[:,2]
last_column
output: array([3, 6, 9])
first_two_vals = np_array[0,0:2]
first_two_vals
output: array([1, 2])
You can use np.take with specifying axis=1
import numpy as np
e = np.array([[ 0, 1, 2, 3, 5, 6, 7, 8],
[ 4, 5, 6, 7, 5, 3, 2, 5],
[ 8, 9, 10, 11, 4, 5, 3, 5]])
e = np.take(e, [1,2,3,4], axis=1)
output:
array([[ 1, 2, 3, 5],
[ 5, 6, 7, 5],
[ 9, 10, 11, 4]])
https://numpy.org/doc/stable/reference/generated/numpy.take.html
>>> arr = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
>>> arr
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
I am deleting the 3rd column as
>>> np.hstack(((np.delete(arr, np.s_[2:], 1)),(np.delete(arr, np.s_[:3],1))))
array([[ 1, 2, 4],
[ 5, 6, 8],
[ 9, 10, 12]])
Are there any better way ?
Please consider this to be a novice question.
If you ever want to delete more than one columns, you just pass indices of columns you want deleted as a list, like this:
>>> a = np.arange(12).reshape(3,4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> np.delete(a, [1,3], axis=1)
array([[ 0, 2],
[ 4, 6],
[ 8, 10]])
>>> import numpy as np
>>> arr = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
>>> np.delete(arr, 2, axis=1)
array([[ 1, 2, 4],
[ 5, 6, 8],
[ 9, 10, 12]])
Something like this:
In [7]: x = range(16)
In [8]: x = np.reshape(x, (4, 4))
In [9]: x
Out[9]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
In [10]: np.delete(x, 1, 1)
Out[10]:
array([[ 0, 2, 3],
[ 4, 6, 7],
[ 8, 10, 11],
[12, 14, 15]])