Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

I have the following problem, I have an numpy array that has empty numpy arrays as elements and its shape is 2x2 but is reported as 2,2,0 actually which makes sense. The problem is when you try to append values to any of the empty numpy arrays nothing happens.

MWE:

import numpy as np

a = np.array([[],[],[],[]])
a = np.reshape(a, (2,2,0))

a[0][0] = np.append(a[0][0], 1)
a[0][1] = np.append(a[0][0], [1])

Output:
>>>a[0][0]
array([], dtype=float64)
>>>a[0][1]
array([], dtype=float64)

Which means that nothing happens. How can I append values to my 2x2 numpy array one at a time?

share|improve this question

After tinkering for a while I realized that the answer is obvious.

When you are trying to add one element on any of the 4 empty numpy arrays you are essentially breaking the 2,2,0 array and somehow the numpy module prevents you from doing so.

If you would like to add the elements one at a time you would have to add them to a temporary 1D array in groups of 4 and then reshape the temporary array into a (2,2,1) shape and then append the full temporary 2x2 numpy array to the empty one, essentially going from a 2,2,0 shape to a 2,2,1 shape.

Repeat as many times as needed. MWE:

import numpy as np

a = np.array([[],[],[],[]])
a = np.reshape(a, (2,2,0))
temporary = np.array([])
for i in range(4):
    temporary = np.append(temporary, i)
temporary = np.reshape(temporary, (2,2,1))
a = np.append(a, temporary)
a = np.reshape(a, (2,2,1))
a = np.append(a, temporary)
a = np.reshape(a, (2,2,2))

And then you can access the elements as a[0][0][0] a[0][0][1]

Sth weird is that when you are appending the temporary array to a it automatically reshapes it to shape (4,)

share|improve this answer
    
While this kind of works, anything based on appending to NumPy arrays is going to be really inefficient, since NumPy isn't designed for that and doesn't use a growth strategy that would make that efficient. You might want to consider using lists for parts of your code where your data structures need to grow dynamically, or find a way to preallocate your array and then fill it instead of using append. – user2357112 Oct 28 '15 at 17:20
    
Totally agree, basically I just need the inner data to be a numpy array, I was just playing with it and it struck me as weird, and then proceeded to find out how I would be able to do it. – Satrapes Oct 28 '15 at 17:29
    
np.append docs says it works with flattened arrays (1d) if you don't specify an axis, hence the (4,) shape. It's superficial similarity to list append is deceiving. – hpaulj Oct 28 '15 at 20:36

a = np.array([[],[],[],[]]) makes

array([], shape=(4, 0), dtype=float64)

This is an array of 0 elements, that contains floats, and has a shape (4,0). Your reshape changes the shape, but not the number of elements - still 2*2*0=0.

This is not an array that contains other arrays.

Appending to an element of a produces a 1 element array with shape (1,)

In [164]: np.append(a[0,0],1)
Out[164]: array([ 1.])

Trying to assign it back to a[0,0] does nothing. Actually I would have expected an error. But in any case, it shouldn't and can't add an value to the array, that by definition, has 0 elements.

You must be thinking that you have defined a 2x2 array where each element can be an object, such as another array. To do that you need create the array differently.

For example:

In [176]: a=np.empty((2,2),dtype=object)
In [177]: a
Out[177]: 
array([[None, None],
       [None, None]], dtype=object)

In [178]: a.fill([])  # lazy way of replacing the None
In [179]: a
Out[179]: 
array([[[], []],
       [[], []]], dtype=object)

Now I have a (2,2) array, where each element can be any Python object, though at the moment they all are empty lists.  As noted in the comment, by using `fill`, each element is the same empty list; change one (in a mutable way), and you change all).

I could use np.append to create a new array (though I don't generally recommend using np.append). (but beware of a[0,0].append(1), a list operation).

In [180]: a[0,0]=np.append(a[0,0],1)    
In [181]: a
Out[181]: 
array([[array([ 1.]), []],
       [[], []]], dtype=object)

I could replace an element with a 2x2 array:

In [182]: a[0,1]=np.array([[1,2],[3,4]])

or a string

In [183]: a[1,0]='astring'

or another list

In [184]: a[1,1]=[1,2,3]

In [185]: a
Out[185]: 
array([[array([ 1.]), array([[1, 2],
       [3, 4]])],
       ['astring', [1, 2, 3]]], dtype=object)

There's a real difference between this (2,2) array of objects and a 3 or 4d array of floats, (2,2,?).


Here's how I'd perform the appends in your answer

create the (2,2,0) array directly:

In [207]: a=np.zeros((2,2,0))

and the (2,2,1) is simply range reshaped:

In [208]: temporary =np.arange(4).reshape(2,2,1)

In [209]: a
Out[209]: array([], shape=(2, 2, 0), dtype=float64)

In [210]: temporary
Out[210]: 
array([[[0],
        [1]],

       [[2],
        [3]]])

np.append is just an alternate front end to concatenate. So I'll use that with explicit control over the axis. append is for Python users who persist in thinking in list terms.

In [211]: np.concatenate([a,temporary],axis=2)
Out[211]: 
array([[[ 0.],
        [ 1.]],

       [[ 2.],
        [ 3.]]])

In [212]: a1=np.concatenate([a,temporary],axis=2)

In [213]: a2=np.concatenate([a1,temporary],axis=2)

In [214]: a2
Out[214]: 
array([[[ 0.,  0.],
        [ 1.,  1.]],

       [[ 2.,  2.],
        [ 3.,  3.]]])

In [215]: a2.shape
Out[215]: (2, 2, 2)
share|improve this answer
    
a.fill([]) is dangerous, since all elements are the same list after that completes. – user2357112 Oct 28 '15 at 18:15
    
All though I'd have to perform mutable list operations on that list element to see such a problem. a[0,0].append(1) would change all elements. The changes I demonstrated replace that initial []. – hpaulj Oct 28 '15 at 18:29

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.