I want to create a numpy array within a numpy array. If i do it with normal python its something like
a = [[1,2], [3,4]]
a[0][1] = [1,1,1]
print a
The result is [[1, [1, 1, 1]], [3, 4]]
How can I achieve the same using numpy arrays? The code I have is:
a = np.array([(1, 2, 3),(4, 5, 6)])
b = np.array([1,1,1])
a[0][1] = b
a as created is dtype int. Each element can only be another integer:
In [758]: a = np.array([(1, 2, 3),(4, 5, 6)])
...: b = np.array([1,1,1])
...:
In [759]: a
Out[759]:
array([[1, 2, 3],
[4, 5, 6]])
In [760]: b
Out[760]: array([1, 1, 1])
In [761]: a[0,1]=b
...
ValueError: setting an array element with a sequence.
You can make another dtype of array, one that holds pointers to objects, much as list does:
In [762]: aO = a.astype(object)
In [763]: aO
Out[763]:
array([[1, 2, 3],
[4, 5, 6]], dtype=object)
Now it is possible to replace one of those element pointers with a pointer to b array:
In [765]: aO[0,1]=b
In [766]: aO
Out[766]:
array([[1, array([1, 1, 1]), 3],
[4, 5, 6]], dtype=object)
But as asked in the comments - why do you want/need to do this? What are you going to do with such an array? It is possible to do some numpy math on such an array, but as shown in some recent SO questions, it is hit-or-miss. It is also slower.
As far as I know, you cannot do this. Numpy arrays cannot have entries of varying shape. Your request to make an array like [[1, [1, 1, 1]], [3, 4]] is impossible. However, you could make a numpy matrix of dimensions (3x2x3) to get
[
[
[1,0,0],
[1,1,1],
[0,0,0],
]
[
[3,0,0],
[4,0,0],
[0,0,0]
]
]
Your only option is to pad empty elements with some number (I used 0s above) or use another data structure.
Related
Im sure this has been answered before as this seems like a pretty trivial question but I cant for the life of me figure out how to add a 2d array to a 1d array along the column so that there are two values in each row.
a = [[1,2,3], [1,3,5], [1,1,1]]
b = [[1], [2], [5]]
so what numpy function can I use to generate
[ [[1,2,3],[1]], [[1,3,5],[2]], [[1,1,1],[5]] ]
Cheers!
this isn't easy with numpy arrays, but you can get the structure you want with:
c = [list(q) for q in zip(a,b)]
# output
[[[1, 2, 3], [1]], [[1, 3, 5], [2]], [[1, 1, 1], [5]]]
casting this to a numpy array gives an array of lists, which is a strange structure and probably not very useful:
arr = np.array(c)
# output:
array([[list([1, 2, 3]), list([1])],
[list([1, 3, 5]), list([2])],
[list([1, 1, 1]), list([5])]], dtype=object)
I stumbled upon what I think is a weird (or at least unintuitive) behavior of numpy and I would like to understand why it behaves that way.
Let's generate a generic array of shape (4, 3, 3).
import numpy as np
arr = np.arange(4*3*3).reshape((4, 3, 3))
Thinking about arr as a list of four three-by-three matrices I want to now swap the first two columns of the first matrix in the list. I can just reorder the columns with an index list:
idx = np.array([1, 0, 2])
m = arr[0]
m[:, idx]
>>> array([[1, 0, 2],
[4, 3, 5],
[7, 6, 8]])
I see that i successfully swapped the two columns. However, if I do try to do same directly with arr, I get:
arr[0, :, idx]
>>> array([[1, 4, 7],
[0, 3, 6],
[2, 5, 8]])
I guess I'm doing something wrong but I don't understand this behavior.
This weird output is because when you are doing
m = arr[0]
m[:, idx]
then m becomes a whole different "array" with data of "arr"
but when you are doing
arr[0, :, arr] there arr is a list which has arrays
I wish to vstack a numpy.array (like building a list) but, I cannot initialize the numpy.array with the correct shape to use numpy.append(numpy.empty/zero/like_empty, etc. did not do the trick... anyway. Finally, I figure the two pieces of code below. Is there someyhing more pythonic? I am using python 3.6.9
import numpy as np
a=[]
n=4
for i in range(n):
'''
some calculation resultinng for example in an numpy.array([[i,i+1,i+2])
'''
a.append(np.array([i,i+1,i+2]))
a=np.array(a).reshape(3,n)
print(a)
or because I prefer to mantain it as a numpy array inside the loop:
import numpy as np
a=np.array([])
n=4
for i in range(n):
'''
some calculation resultinng for example in an numpy.array [i,i+1,i+2]
'''
if a.size == 0:
a=np.array([i,i+1,i+2])
else:
a=np.vstack((a,np.array([i,i+1,i+2])))
print(a)
both output:
[[0 1 2]
[1 2 3]
[2 3 4]
[3 4 5]]
Your first use, with list append:
In [146]: alist=[]
In [147]: for i in range(4):
...: alist.append(np.arange(i,i+3))
...:
In [148]: alist
Out[148]: [array([0, 1, 2]), array([1, 2, 3]), array([2, 3, 4]), array([3, 4, 5])]
and make the array:
In [149]: np.array(alist)
Out[149]:
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5]])
or since vstack is happy with a list of arrays:
In [150]: np.vstack(alist)
Out[150]:
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5]])
You could use vstack in the loop:
In [151]: arr = np.zeros((0,3),int)
In [152]: for i in range(4):
...: arr = np.vstack((arr, np.arange(i,i+3)))
...:
In [153]: arr
Out[153]:
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5]])
This has two problems:
it is slower; list append operates in-place simply adding a pointer to the list. vstack makes whole new array each time, with a full copy!
it is harder to initialize, as you found out. You actually have to understand array shapes, and what concatenate does when it combines 2 or more arrays. Here I started with a (0,3) array.
np.array([np.arange(i, i+3) for i in range(n)])
How to create an numpy array with shape [2, 2, 3], where the elements at axis 2 is another array, for example [1, 2, 3]?
So I would like to do something like this invalid code:
a = np.arange(1, 4)
b = np.full((3, 3), a)
Resulting in an array like:
[[[ 1. 2. 3.]
[ 1. 2. 3.]]
[[ 1. 2. 3.]
[ 1. 2. 3.]]]
Could of course make the loop for filling like, but thought there may be a shortcut:
for y in range(b.shape[0]):
for x in range(b.shape[1]):
b[y, x, :] = a
There are multiple ways to achieve this. One is to use np.full in np.full((2,2,3), a) as pointed out by Divakar in the comments. Alternatively, you can use np.tile for this, which allows you to construct an array by repeating an input array a given number of times. To construct your example you could do:
import numpy as np
np.tile(np.arange(1, 4), [2, 2, 1])
If your numpy version is >= 1.10 you can use broadcast_to
a = np.arange(1,4)
a.shape = (1,1,3)
b = np.broadcast_to(a,(2,2,3))
This produces a view rather than copying so will be quicker for large arrays.
EDIT this looks to be the result you're asking for with your demo.
Based on Divakar comment, an answer can also be:
import numpy as np
np.full([2, 2, 3], np.arange(1, 4))
Yet another possibility is:
import numpy as np
b = np.empty([2, 2, 3])
b[:] = np.arange(1, 4)
Also using np.concatenate or it's wrapper np.vstack
In [26]: a = np.arange(1,4)
In [27]: np.vstack([a[np.newaxis, :]]*4).reshape(2,2, 3)
Out[27]:
array([[[1, 2, 3],
[1, 2, 3]],
[[1, 2, 3],
[1, 2, 3]]])
In [28]: np.concatenate([a[np.newaxis, :]]*4, axis=0).reshape(2,2, 3)
Out[28]:
array([[[1, 2, 3],
[1, 2, 3]],
[[1, 2, 3],
[1, 2, 3]]])
What is the difference between a numpy array (lets say X) that has a shape of (N,1) and (N,). Aren't both of them Nx1 matrices ? The reason I ask is because sometimes computations return either one or the other.
This is a 1D array:
>>> np.array([1, 2, 3]).shape
(3,)
This array is a 2D but there is only one element in the first dimension:
>>> np.array([[1, 2, 3]]).shape
(1, 3)
Transposing gives the shape you are asking for:
>>> np.array([[1, 2, 3]]).T.shape
(3, 1)
Now, look at the array. Only the first column of this 2D array is filled.
>>> np.array([[1, 2, 3]]).T
array([[1],
[2],
[3]])
Given these two arrays:
>>> a = np.array([[1, 2, 3]])
>>> b = np.array([[1, 2, 3]]).T
>>> a
array([[1, 2, 3]])
>>> b
array([[1],
[2],
[3]])
You can take advantage of broadcasting:
>>> a * b
array([[1, 2, 3],
[2, 4, 6],
[3, 6, 9]])
The missing numbers are filled in. Think for rows and columns in table or spreadsheet.
>>> a + b
array([[2, 3, 4],
[3, 4, 5],
[4, 5, 6]])
Doing this with higher dimensions gets tougher on your imagination.