Hi I'd like to create a 10 x 5 matrix with the first column filled with 1 to 10 and the subsequent columns filled with 2, 3, 4 and 5 times the values of the first column.
I've made things work with the following code, but is there a shorter way to do this?
import numpy as np
mat = np.zeros([10,5])
mat[:,0] = np.arange(1,11)
mat[:,1] = np.dot(mat[:,0],2)
mat[:,2] = np.dot(mat[:,0],3)
mat[:,3] = np.dot(mat[:,0],4)
mat[:,4] = np.dot(mat[:,0],5)
I think you can achieve this by outer product.
Try:
import numpy as np
a = np.arange(1, 11).reshape(-1, 1) # column vector (1,2,3,...,10)
b = np.arange(1, 6).reshape(1, -1) # row vector (1,2,3,...,5)
np.matmul(a, b) # matrix of entries of multiplication of the indices (1-based indices)
or the one-liner:
np.arange(1, 11).reshape(-1, 1) * np.arange(1, 6).reshape(1, -1)
This works for me:
>>> np.array([np.array([1,2,3,4,5]) * i for i in range(1,11)])
array([[ 1, 2, 3, 4, 5],
[ 2, 4, 6, 8, 10],
[ 3, 6, 9, 12, 15],
[ 4, 8, 12, 16, 20],
[ 5, 10, 15, 20, 25],
[ 6, 12, 18, 24, 30],
[ 7, 14, 21, 28, 35],
[ 8, 16, 24, 32, 40],
[ 9, 18, 27, 36, 45],
[10, 20, 30, 40, 50]])
This is exactly what builtin numpy outer does:
>>> np.outer(np.arange(1, 11), np.arange(1, 6))
array([[ 1, 2, 3, 4, 5],
[ 2, 4, 6, 8, 10],
[ 3, 6, 9, 12, 15],
[ 4, 8, 12, 16, 20],
[ 5, 10, 15, 20, 25],
[ 6, 12, 18, 24, 30],
[ 7, 14, 21, 28, 35],
[ 8, 16, 24, 32, 40],
[ 9, 18, 27, 36, 45],
[10, 20, 30, 40, 50]])
Related
Is it possible to apply few conditions to numpy.array while indexing them? In my case I want to show first 10 elements and then 2 neighbour elements with step 5:
numpy.arange(40)
#Output is:
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, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39])
Applying my conditions to this array I want to get this:
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 14, 15, 20, 21, 26, 27, 32,
33, 38, 39])
I haven't found any solution. I thought it should look something like this:
np.arange(40)[0:10, 10:len(np.arange(40)):5]
But it's not working for me.
You can try custom indexing on reshaped array:
n = 40
idx = np.zeros(n//2, dtype=bool)
idx[:5] = True
idx[4:None:3] = True
>>> np.arange(n).reshape(-1,2)[idx]
array([[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7],
[ 8, 9],
[14, 15],
[20, 21],
[26, 27],
[32, 33],
[38, 39]])
>>> np.arange(n).reshape(-1,2)[idx].ravel()
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 14, 15, 20, 21, 26, 27, 32,
33, 38, 39])
If I have a list:
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
I would like to cast the above list into an array with the following arrangements of the elements:
array([[ 1, 2, 3, 7, 8, 9]
[ 4, 5, 6, 10, 11, 12]
[13, 14, 15, 19, 20, 21]
[16, 17, 18, 22, 23, 24]])
How do I do this or what is the best way to do this? Many thanks.
I have done this in a crude way below where I will just get all the sub-matrix and then concatenate all of them at the end:
np.array(results[arr.shape[0]*arr.shape[1]*0:arr.shape[0]*arr.shape[1]*1]).reshape(arr.shape[0], arr.shape[1])
array([[1, 2, 3],
[4, 5, 6]])
np.array(results[arr.shape[0]*arr.shape[1]*1:arr.shape[0]*arr.shape[1]*2]).reshape(arr.shape[0], arr.shape[1])
array([[ 7, 8, 9],
[ 10, 11, 12]])
etc,
But I will need a more generalized way of doing this (if there is one) as I will need to do this for an array of any size.
You could use the reshape function from numpy, with a bit of indexing :
a = np.arange(24)
>>> a
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])
Using reshape and a bit of indexing :
a = a.reshape((8,3))
idx = np.arange(2)
idx = np.concatenate((idx,idx+4))
idx = np.ravel([idx,idx+2],'F')
b = a[idx,:].reshape((4,6))
Ouptut :
>>> b
array([[ 0, 1, 2, 6, 7, 8],
[ 3, 4, 5, 9, 10, 11],
[12, 13, 14, 18, 19, 20],
[15, 16, 17, 21, 22, 23]])
Here the tuple (4,6) passed to reshape indicates that you want your array to be 2 dimensional, and have 4 arrays of 6 elements. Those values can be computed.
Then we compute the index to set the correct order of the data. Obvisouly, this a complicated bit here. As I'm not sure what you mean by "any size of data", its difficult for me to give you a agnostic way to compute that index.
Obviously, if you are using a list and not an np.array, you might have to convert the list first, for example by using np.array(your_list).
Edit :
I'm not sure if this exactly what you are after, but this should work for any array evenly divisible by 6 :
def custom_order(size):
a = np.arange(size)
a = a.reshape((size//3,3))
idx = np.arange(2)
idx = np.concatenate([idx+4*i for i in range(0,size//(6*2))])
idx = np.ravel([idx,idx+2],'F')
b = a[idx,:].reshape((size//6,6))
return b
>>> custom_order(48)
array([[ 0, 1, 2, 6, 7, 8],
[ 3, 4, 5, 9, 10, 11],
[12, 13, 14, 18, 19, 20],
[15, 16, 17, 21, 22, 23],
[24, 25, 26, 30, 31, 32],
[27, 28, 29, 33, 34, 35],
[36, 37, 38, 42, 43, 44],
[39, 40, 41, 45, 46, 47]])
If I have a 3D array of ([4,3,3]) like this:
[[0,1,2] [[9,10,11 ] [[18,19,20] [[27,28,29]
[3,4,5] [12,13,14] [21,22,23] [30,31,32]
[6,7,8]] , [15,16,17]] , [24,25,26]] , [33,34,35]]
How would I convert it to a 2D array of ([6,6]) like this so that the 1st half of arrays are at the top half of the 160x160 and the 2nd half are at the bottom:
[[0,1,2,9,10,11]
[3,4,5,12,13,14]
[6,7,8,15,16,17]
[18,19,20,27,28,29]
[21,22,23,30,31,32]
[24,25,26,33,34,35]]
My array creation:
qDCTReversed = np.zeros((400,8,8), dtype=np.int)
And I need a (160,160) array.
A very fast one line solution using no for-loops is this:
# initialization
qDCTReversed = np.arange(4*3*3).reshape((4,3,3))
# calculation
qDCTReversed = qDCTReversed.reshape((2,2,3,3)).transpose((0,2,1,3)).reshape((6,6))
or for the (400,8,8) array:
qDCTReversed.reshape((20,20,8,8)).transpose((0,2,1,3)).reshape((160,160))
Speed comparison:
Mstaino's answer: 0.393 ms
yatu's answer: 0.138 ms
This answer: 0.016 ms
You can do this by looping over the list as such:
a = [[[ 0, 1, 2], [ 9,10,11]],
[[ 3, 4, 5], [12,13,14]],
[[ 6, 7, 8], [15,16,17]],
[[18,19,20], [27,28,29]],
[[21,22,23], [30,31,32]],
[[24,25,26], [33,34,35]]]
b = [[i for j in k for i in j ] for k in a]
print(b)
outputs:
[ 0, 1, 2, 9, 10, 11]
[ 3, 4, 5, 12, 13, 14]
[ 6, 7, 8, 15, 16, 17]
[18, 19, 20, 27, 28, 29]
[21, 22, 23, 30, 31, 32]
[24, 25, 26, 33, 34, 35]
The reshape you ask can be done with:
x = np.arange(36).reshape((4,3,3))
np.vstack(np.hstack(x[2*i:2+2*i]) for i in range(x.shape[0]//2))
>>array([[ 0, 1, 2, 9, 10, 11],
[ 3, 4, 5, 12, 13, 14],
[ 6, 7, 8, 15, 16, 17],
[18, 19, 20, 27, 28, 29],
[21, 22, 23, 30, 31, 32],
[24, 25, 26, 33, 34, 35]])
First time i ask something here. I am kind of 'blocked'.
I have an array composed of n x n arrays (lets take n=3 for simplification):
[
[
[ 0, 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]
]
]
(altho my array contains a lot more than 3 3*3 arrays)
i want to achieve a 2D array like this :
[0,1,2,9,10,11,18,19,20]
[3,4,5,12,13,14,21,22,23]
[6,7,8,15,16,17,24,25,26]
Is there a trick i haven't thought of because i cant think of any way to accomplish the transformation.
Thanks
Slightly cleaner than moveaxis maybe:
import numpy as np
a = np.arange(27).reshape(3,3,3)
a.swapaxes(0,1).reshape(3,-1)
array([[ 0, 1, 2, 9, 10, 11, 18, 19, 20],
[ 3, 4, 5, 12, 13, 14, 21, 22, 23],
[ 6, 7, 8, 15, 16, 17, 24, 25, 26]])
Think of this as a list of 3 arrays, that you want to join horizontally:
In [171]: arr = np.arange(27).reshape(3,3,3)
In [172]: np.hstack(arr)
Out[172]:
array([[ 0, 1, 2, 9, 10, 11, 18, 19, 20],
[ 3, 4, 5, 12, 13, 14, 21, 22, 23],
[ 6, 7, 8, 15, 16, 17, 24, 25, 26]])
In [173]: arr
Out[173]:
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],
[24, 25, 26]]])
Of I like to test ideas with arrays with differing dimensions. Then the various axis manipulations becomes more obvious.
In [174]: arr = np.arange(24).reshape(2,3,4)
In [175]: arr
Out[175]:
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]]])
In [176]: np.hstack(arr)
Out[176]:
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]])
In [177]: np.vstack(arr)
Out[177]:
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]])
But there's nothing wrong with the variations on the transpose and reshape answers, if starting from a 3d array (as opposed to a list of arrays):
In [187]: arr.transpose(1,0,2).reshape(3,-1)
Out[187]:
array([[ 0, 1, 2, 9, 10, 11, 18, 19, 20],
[ 3, 4, 5, 12, 13, 14, 21, 22, 23],
[ 6, 7, 8, 15, 16, 17, 24, 25, 26]])
You could use np.block
>>> import numpy as np
>>> X = np.arange(27).reshape(3, 3, 3)
>>>
>>> np.block(list(X))
array([[ 0, 1, 2, 9, 10, 11, 18, 19, 20],
[ 3, 4, 5, 12, 13, 14, 21, 22, 23],
[ 6, 7, 8, 15, 16, 17, 24, 25, 26]])
A simple reshape doesn't suffice since you have to change the order of the axes first:
import numpy as np
a = np.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],[24,25,26]]])
np.moveaxis(a, 0, 1).reshape(3,9)
[[ 0 1 2 9 10 11 18 19 20]
[ 3 4 5 12 13 14 21 22 23]
[ 6 7 8 15 16 17 24 25 26]]
I can easily convert a symmetric matrix to an array/1-d matrix of one of its triangular components using
A_symmetric = np.matrix([[1,2][2,3]])
A_array = A_symmetric[np.triu_indices(2)] == np.matrix([1,2,3])
(and similary with tril_indices)
But how can I reverse this operations, i.e. how do I get a symmetric matrix from the array/1-d matrix given by triu_indices?
If you are ok with arrays instead of matrices you could simply preallocate and assign:
>>> i, j = np.triu_indices(8)
>>> a = np.arange(i.size)
>>> M = np.empty((8, 8), a.dtype)
>>> M[i, j] = a
>>> M[j, i] = a
>>> M
array([[ 0, 1, 2, 3, 4, 5, 6, 7],
[ 1, 8, 9, 10, 11, 12, 13, 14],
[ 2, 9, 15, 16, 17, 18, 19, 20],
[ 3, 10, 16, 21, 22, 23, 24, 25],
[ 4, 11, 17, 22, 26, 27, 28, 29],
[ 5, 12, 18, 23, 27, 30, 31, 32],
[ 6, 13, 19, 24, 28, 31, 33, 34],
[ 7, 14, 20, 25, 29, 32, 34, 35]])