Brandon Ginley
Brandon Ginley

Reputation: 269

Python: Creation of array with fill values according to column/row

10x10 array

Suppose you are trying to create a synthetic image 10x10 represented by a matrix of values (numpy array). This image has three blocked sections. In the upper left block, columns 0-4 and rows 0-4, the value will be 1. the right block, columns 5-9 and rows 0-9, will be 0. the remaining area, columns 0-4 and row 5-9, will be 2.(see attached image)

What is the fastest way to create such an object? I understand that you could create an array of zeros and iteratively change the values in each column, but I also understand this is not an efficient method. I assume it involves simply generating the array using np.array, but I'm not quite sure of the syntax.

Upvotes: 2

Views: 5209

Answers (4)

Benjamin
Benjamin

Reputation: 11860

For simple patterns similar to yours, you can use basic broadcasting:

>>> numpy.array([1]*5 + [2]*5)[:,None] * numpy.array([1]*5 + [0]*5)
array([[1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [2, 2, 2, 2, 2, 0, 0, 0, 0, 0],
       [2, 2, 2, 2, 2, 0, 0, 0, 0, 0],
       [2, 2, 2, 2, 2, 0, 0, 0, 0, 0],
       [2, 2, 2, 2, 2, 0, 0, 0, 0, 0],
       [2, 2, 2, 2, 2, 0, 0, 0, 0, 0]])

[:,None] just adds a second axis, so that instead of a (10,) size array, we have a (10,1) size array which we can then multiply with the (10,) array on the right using broadcasting.

Or, more concisely:

>>> numpy.outer([1]*5 + [2]*5, [1]*5 + [0]*5)

which gives the same result.

Upvotes: 0

hpaulj
hpaulj

Reputation: 231395

My first thought is to create an 'empty' array of 0, and then fill the blocks of 1 and 2. E.g.

In [145]: C = np.zeros((10,10), int)

In [146]: C[:4,:4]=1

In [147]: C[:4,5:9]=2

In [148]: C
Out[148]: 
array([[1, 1, 1, 1, 0, 2, 2, 2, 2, 0],
       [1, 1, 1, 1, 0, 2, 2, 2, 2, 0],
       [1, 1, 1, 1, 0, 2, 2, 2, 2, 0],
       [1, 1, 1, 1, 0, 2, 2, 2, 2, 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, 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, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

You could also make the blocks (with np.ones etc), and concatenate them. hstack and vstack are just alternative APIs for concatenate. But concatenate ends up using, in compiled code, this initialize and assign method. It's a good idea to be familiar with both methods.

Upvotes: 2

Ed Smith
Ed Smith

Reputation: 13206

What about,

import numpy as np

a = np.ones((5,5))
b = a*2.
c = np.zeros((10,5))

np.hstack((np.vstack((a,b)),c))

Upvotes: 1

maxymoo
maxymoo

Reputation: 36545

Is this a homework question? Have a play with numpy.concatenate and numpy.ones and see how you go.

Upvotes: 0

Related Questions