1

I'm trying to append one numpy array to another numpy array, like this:

import numpy as np
meanings = 2
signals = 4

def new_agent(agent_type, context_size):
    if agent_type == 'random':
        comm_system = np.random.random_integers(0, 1, (meanings, signals))
    if agent_type == 'blank':
        comm_system = np.zeros((meanings, signals), int)
    score_list = np.array([0., 0., 0., 0.])
    np.append(comm_system, score_list)
    np.append(comm_system, context_size)
    return comm_system

if I now call:

random_agent = new_agent('random', 5)

I expect to get something like:

[[0 1 0 0]
[1 1 0 1]
[0. 0. 0. 0.]
5]

But instead I get only:

[[0 1 0 0]
[1 1 0 1]]

So the score_list and the context_size don't get appended. And the same holds for when I call new_agent() with 'blank'.

Thanks!

Marieke_W
  • 941
  • 1
  • 7
  • 5

3 Answers3

5

You can use hstack and vstack to concatenate arrays:

>>> from numpy import array, hstack, vstack
>>> a = array([1, 2, 3])
>>> b = array([4, 5, 6])

>>> hstack([a, b])
array([1, 2, 3, 4, 5, 6])

>>> vstack([a, b])
array([[1, 2, 3],
       [4, 5, 6]])
Roberto Bonvallet
  • 31,943
  • 5
  • 40
  • 57
  • the docs use the round (a,b) brackets not the square ones to hstack https://docs.scipy.org/doc/numpy/user/quickstart.html#fancy-indexing-and-index-tricks see hstack – droid192 Dec 26 '18 at 11:07
2

numpy.append() returns a new array containing the data from its inputs together. It does not modify the inputs themselves, and there would be no way for it to do so. This is because arrays in NumPy are generally not resizable.

Try changing your code to capture the value returned from append(), which will be the array you want.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
1

@John is correct about how to use the return value from numpy.append because it doesn't modify the original array. However, there's a problem with your expected output:

[[0 1 0 0]
 [1 1 0 1]
 [0. 0. 0. 0.]
 5]

is not a possible numpy array because of two reasons: one is that some elements are integers and some are floats, but a numpy array's dtype must be uniform; the other is that each row is not the same length, but numpy arrays must have uniform (rectangular) shape.

I think what you might rather do is to just return all three things:

  • comm_system as an array of ints,
  • score_list as an array of floats,
  • and context_size as an int (not an array).

You can do that with a tuple:

def new_agent(agent_type, context_size):
    if agent_type == 'random':
        comm_system = np.random.random_integers(0, 1, (meanings, signals))
    if agent_type == 'blank':
        comm_system = np.zeros((meanings, signals), int)
    score_list = np.zeros(signals)  #This is different too! No need to type out the 0, 0, ...
    # now just return all three:
    return comm_system, score_list, context_size

Then you can "unpack" the tuple like so:

random_agent, scores, size = new_agent('random', 5)

Or just keep them all in one tuple:

random_agent_info = new_agent('random', 5)

And you'll have

In [331]: random_agent, scores, size = new_agent('random', 5)

In [332]: random_agent
Out[332]: 
array([[0, 1, 1, 0],
       [0, 1, 0, 1]])

In [333]: scores
Out[333]: array([ 0.,  0.,  0.,  0.])

In [334]: size
Out[334]: 5

In [336]: random_agent_info
Out[336]: 
(array([[1, 1, 0, 1],
        [0, 1, 0, 0]]),
 array([ 0.,  0.,  0.,  0.]),
 5)

In [337]: random_agent_info[0]
Out[337]: 
array([[1, 1, 0, 1],
       [0, 1, 0, 0]])

In [338]: random_agent_info[1]
Out[338]: array([ 0.,  0.,  0.,  0.])

In [339]: random_agent_info[2]
Out[339]: 5

If you do want to have the comm_system and score_list to be one (3,2) array, you can do that with:

def new_agent(agent_type, context_size):
    ...
    return np.vstack([comm_system, score_list]), context_size

Then you'll get one array and one int:

In [341]: random_agent, size = new_agent('random', 5)

In [342]: random_agent
Out[342]: 
array([[ 1.,  0.,  1.,  1.],
       [ 1.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  0.]])

In [343]: size
Out[343]: 5
askewchan
  • 45,161
  • 17
  • 118
  • 134