8

I have an empty numpy array, and another one populated with values. I want to fill the empty numpy array with the populated one, x times. So, when x = 3, the (originally empty array) would look like [[populated_array],[populated_array], [populated_array]]

Where populated_array is the same value/array each time. I have tried this

a = np.empty(3)
a.fill(np.array([4,6,6,1]))

but get this

ValueError: Input object to FillWithScalar is not a scalar

and want this

[[4,6,6,1],[4,6,6,1],[4,6,6,1]]

cheers for any help.

harry lakins
  • 803
  • 1
  • 13
  • 28

6 Answers6

10

tile and repeat are handy functions when you want to repeat an array in various ways:

In [233]: np.tile(np.array([4,6,6,1]),(3,1))
Out[233]: 
array([[4, 6, 6, 1],
       [4, 6, 6, 1],
       [4, 6, 6, 1]])

On the failure, note the docs for fill:

a.fill(value)

Fill the array with a scalar value.

np.array([4,6,6,1]) is not a scalar value. a was initialized as a 3 element float array.

It is possible to assign values to elements of an array, provided the shapes are right:

In [241]: a=np.empty(3)
In [242]: a[:]=np.array([1,2,3])    # 3 numbers into 3 slots
In [243]: a
Out[243]: array([ 1.,  2.,  3.])
In [244]: a=np.empty((3,4))
In [245]: a[:]=np.array([1,2,3,4])   # 4 numbers into 4 columns
In [246]: a
Out[246]: 
array([[ 1.,  2.,  3.,  4.],
       [ 1.,  2.,  3.,  4.],
       [ 1.,  2.,  3.,  4.]])

This fill works with an object type array, but the result is quite different, and should be used with considerable caution:

In [247]: a=np.empty(3, object)
In [248]: a
Out[248]: array([None, None, None], dtype=object)
In [249]: a.fill(np.array([1,2,3,4]))
In [250]: a
Out[250]: array([array([1, 2, 3, 4]), array([1, 2, 3, 4]), array([1, 2, 3, 4])], dtype=object)

This (3,) array is not the same as the (3,4) array produced by other methods. Each element of the object array is a pointer to the same thing. Changing a value in one element of a changes that value in all the elements (because they are the same object).

In [251]: a[0][3]=5
In [252]: a
Out[252]: array([array([1, 2, 3, 5]), array([1, 2, 3, 5]), array([1, 2, 3, 5])], dtype=object)
hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • 2
    I _thought_ that there should be a shortcut for this. On the other hand ... It seems silly to provide a shortcut when most of the time you don't need to expand the array if you use broadcasting and indexing tricks effectively ... – mgilson Dec 08 '16 at 18:07
  • `np.tile` might be an old answer to MATLAB `repmat`. It's a Python function, and makes use of the compiled `repeat`. With broadcasting it isn't as essential. – hpaulj Dec 08 '16 at 18:13
5

Use broadcasting

vstack, tile, and repeat are all great and whatnot, but broadcasting can be several orders of magnitude faster...

import numpy as np
from time import time

t = time()
for _ in xrange(10000):
    a = np.array([4,6,6,1])
    b = np.vstack((a,)*100)
print time()-t

t = time()
for _ in xrange(10000):
    a = np.array([4,6,6,1])
    b = np.tile(a,(3,1))
print time()-t

t = time()
for _ in xrange(10000):
    a = np.array([4,6,6,1])
    b = np.empty([100,a.shape[0]])
    b[:] = a
print time()-t

prints:

2.76399993896
0.140000104904
0.0490000247955
Aaron
  • 10,133
  • 1
  • 24
  • 40
2

You can vstack it:

>>> a = np.array([4,6,6,1])
>>> np.vstack((a,)*3)
array([[4, 6, 6, 1],
       [4, 6, 6, 1],
       [4, 6, 6, 1]])

Note that you frequently don't need to do this... You can do a lot of neat tricks with numpy's broadcasting...:

>>> a = np.array([4,6,6,1])
>>> ones = np.ones((4, 4))
>>> ones * a
array([[ 4.,  6.,  6.,  1.],
       [ 4.,  6.,  6.,  1.],
       [ 4.,  6.,  6.,  1.],
       [ 4.,  6.,  6.,  1.]])

In some cases, you can also use np.newaxis and ... to do neat things as well. It's probably worth looking at numpy's indexing documentation to get familiar with the options.

mgilson
  • 300,191
  • 65
  • 633
  • 696
1

As the Numpy Array Documentation states, first param is shape, son when you're doing:

a = np.empty(3)

You're creating an array of dimension 3 (just one dimension). Instead, you should do:

a = np.empty([3,3])

That creates an array of 3 subarrays of dimension each with dimension 3 (that is a matrix 3x3).

As the Numpy fill Documentation states, fill only takes a number(scalar) as param, so you cannot use another array as argument and what you had done isn't properly working:

a.fill(np.array([4,6,6,1]))

To achieve what you're trying to do, I would do:

a = np.array([[4,6,6,1]]*3)

Hope my comments help you!

0

Repeating tasks like this often get reduced to matrix or vector operations. np.outer() can do it even faster than multiplication with the eye matrix or filling in empty array:

>>>a = np.array([4,6,6,1])
>>>b = np.outer(np.ones(3, dtype=np.int), a)
>>>b
array([[4, 6, 6, 1],
       [4, 6, 6, 1],
       [4, 6, 6, 1]])
Anton K
  • 4,658
  • 2
  • 47
  • 60
0

You could use np.full(), as described here.

>>>repetitions = 3
>>>fill_array = np.array([4,6,6,1])
>>>fill_shape = np.shape(fill_array)
>>>a = np.full([*(repetitions,),*fill_shape],fill_array)
>>>a
array([[4, 6, 6, 1],
       [4, 6, 6, 1],
       [4, 6, 6, 1]])
janosch
  • 3
  • 2