maelstromscientist
maelstromscientist

Reputation: 551

Storing 2D array inside a larger 3D array

I'm trying to store multiple 2D arrays (STAR) inside of a larger 3D array (called STACK) that can continue to grow in size. I need STACK to be a global parameter that can be accessed by multiple functions at any time. To do this I tried using numpy.dstack() So far this is what my code looks like:

box_size = np.shape(star)[0]
# The 2D array I'm trying to add to the STACK
STAR = [[1, 1, 1, 1, 1],\
        [1, 1, 2, 1, 1],\
        [1, 2, 3, 2, 1],\
        [1, 1, 2, 1, 1],\
        [1, 1, 1, 1, 1,]]
# Initialize STACK to be an empty array the same size as STAR
STACK = np.zeros((2*(box_size/2)+1,2*(box_size/2)+1))

# A function that appends STAR to STACK
def add_Star(STAR):
    np.dstack((STACK,STAR))

# Call the function
add_Star(STAR)

However when I try to print the updated STACK, I get

[[ 0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.]]

I don't know if I'm missing something obvious or completely misusing the function.

To be clear, I'd like STACK to be a memory of every STAR I add to it. That is, I'd like each STAR to be accessible in the STACK if I need, to say, remove it later. In practice every STAR is going to be different, so simply adding STACK to STAR isn't going to work.

Upvotes: 0

Views: 2135

Answers (3)

hpaulj
hpaulj

Reputation: 231385

Let's streamline your action a bit, to better understand what is going on

In [125]: n=5

Make star an array, a 5x5 one using your values

In [126]: star=np.array([[1, 1, 1, 1, 1],\  # don't need the \
        [1, 1, 2, 1, 1],\
        [1, 2, 3, 2, 1],\
        [1, 1, 2, 1, 1],\
        [1, 1, 1, 1, 1,]])
In [127]: star
Out[127]: 
array([[1, 1, 1, 1, 1],
       [1, 1, 2, 1, 1],
       [1, 2, 3, 2, 1],
       [1, 1, 2, 1, 1],
       [1, 1, 1, 1, 1]])

initial stack to zeros of the same size. This is not the same as an 'empty' array.

In [128]: stack=np.zeros((5,5))

In [130]: newstack=np.dstack((stack,star))
In [131]: newstack.shape
Out[131]: (5, 5, 2)

dstack is not like the list append. It makes a new array. Note the shape - 3d.

In [132]: newstack
Out[132]: 
array([[[ 0.,  1.],
        [ 0.,  1.],
        [ 0.,  1.],
        [ 0.,  1.],
        [ 0.,  1.]],
....

Note, it has the zeros plus the star values.

In [133]: newstack=np.dstack((newstack,star))
In [134]: newstack.shape
Out[134]: (5, 5, 3)

Do you really want to do this?

Here's a better way of building a 3d array incrementally:

In [135]: alist=[]
In [136]: alist.append(star)
In [137]: alist.append(star)
In [138]: alist
Out[138]: 
[array([[1, 1, 1, 1, 1],
        [1, 1, 2, 1, 1],
        [1, 2, 3, 2, 1],
        [1, 1, 2, 1, 1],
        [1, 1, 1, 1, 1]]), array([[1, 1, 1, 1, 1],
        [1, 1, 2, 1, 1],
        [1, 2, 3, 2, 1],
        [1, 1, 2, 1, 1],
        [1, 1, 1, 1, 1]])]
In [139]: np.array(alist)
Out[139]: 
array([[[1, 1, 1, 1, 1],
        [1, 1, 2, 1, 1],
        [1, 2, 3, 2, 1],
        [1, 1, 2, 1, 1],
        [1, 1, 1, 1, 1]],

...)
In [140]: _.shape
Out[140]: (2, 5, 5)

Note that np.array joins the components along a new axis, at the front. This is the better place for doing that in numpy.

You mention removing a 'star' later; that will be easier if you leave it in the list form. The 3d array form is useful if you need to do calculations across 'star', but otherwise might not be needed.


Or if you know how many star you will have, you can initial the stack to the right size, and assign values:

In [146]: stack=np.zeros((2,5,5),dtype=int)
In [147]: stack[0,:,:] = star
In [148]: stack[1,:,:] = star*2
In [149]: stack
Out[149]: 
array([[[1, 1, 1, 1, 1],
        [1, 1, 2, 1, 1],
        [1, 2, 3, 2, 1],
        [1, 1, 2, 1, 1],
        [1, 1, 1, 1, 1]],

       [[2, 2, 2, 2, 2],
        [2, 2, 4, 2, 2],
        [2, 4, 6, 4, 2],
        [2, 2, 4, 2, 2],
        [2, 2, 2, 2, 2]]])

This too is better than repeatedly using dstack (or some other concatenation).

Upvotes: 0

S E Clark
S E Clark

Reputation: 423

There seem to be a few confusions here.

First, the following code should do what you want it to, with as few changes as possible:

# The 2D array I'm trying to add to the STACK
STAR = [[1, 1, 1, 1, 1],\
        [1, 1, 2, 1, 1],\
        [1, 2, 3, 2, 1],\
        [1, 1, 2, 1, 1],\
        [1, 1, 1, 1, 1,]]
STAR = np.asarray(STAR)


# Initialize STACK to be an empty array the same size as STAR
STACK = np.zeros(STAR.shape, np.float_)

# A function that appends STAR to STACK
def add_Star(star):
    out = np.dstack((STACK,star))

    return out

# Call the function
STACK = add_Star(STAR)

Now let's break down why. Most importantly, the variables in your function e.g. the star in

def add_Star(star)

don't have to be the same names as variables elsewhere in your code (and in fact shouldn't, because it's confusing). Only in the function call

STACK = add_Star(STAR)

do you need to feed the function some variable defined elsewhere.

You'll notice that I also added return to the function, because I interpreted your question as wanting to be able to run add_Star repeatedly, and each time to output an expanded STACK.

Also, an easy way to see the dimensions of any given array is

array.shape

You'll see I used that to define the shape of STACK, rather than going through the extra step of defining a box_size.

Finally, STAR as you had it defined was not in array form. When using numpy, it's easy to just use np.asarray to get a list like you had into array format.

Upvotes: 1

bbkglb
bbkglb

Reputation: 769

You could do this using lists by using the append function:

STAR_1 = [[1, 1, 1, 1, 1],\
         [1, 1, 2, 1, 1],\
         [1, 2, 3, 2, 1],\
         [1, 1, 2, 1, 1],\
         [1, 1, 1, 1, 1,]]

STACK = [STAR_1]

STAR_2 = [[2, 2, 2, 2, 2],\
         [1, 1, 2, 1, 1],\
         [1, 2, 3, 2, 1],\
         [1, 1, 2, 1, 1],\
         [1, 1, 1, 1, 1,]]

STACK.append(STAR_2)
print(STACK)

This will print:

[[[1, 1, 1, 1, 1],
  [1, 1, 2, 1, 1],
  [1, 2, 3, 2, 1],
  [1, 1, 2, 1, 1],
  [1, 1, 1, 1, 1]],
 [[2, 2, 2, 2, 2],
  [1, 1, 2, 1, 1],
  [1, 2, 3, 2, 1],
  [1, 1, 2, 1, 1],
  [1, 1, 1, 1, 1]]]

Upvotes: 0

Related Questions