4

Say there's two 2D arrays, a and b

import numpy as np
a = np.random.rand(3, 4)
b = np.random.zeros(8, 8)

and b is always larger than a over both axes.

(Edit: b is initialized as an array of zeros, to reflect the fact that all elements not occupied by a will remain zero.)

Question. What's the fastest or most Pythonic way to "insert" a into b?

So far I've tried 2 things:

  1. Using np.pad to "turn" a into an array of shape (8, 8)
  2. Loop through every row in a and place it in some the corresponding row in b

What I haven't tried is using a doubly-nested loop to iterate over every element of a, since I think that's not performance-friendly.

Motivation. Each array a is a tiny character, and I'd like to feed each character to a neural net that accepts flattened arrays of shape (8, 8), ie. arrays of shape (64,). (I think I can't simply flatten a to one dimension and pad it with zeros because then its two-dimensional structure gets warped, so, rather, I must first "reshape" it into (8, 8), right?) There's a few millions of characters.

7
  • You speak of padding with zeroes in the last paragraph, but in the example you present b with random values. So what do you need: a padded with the values from b, or padded with zeroes? Is the padding at the right and bottom? Commented Sep 19, 2016 at 6:28
  • what is meant by "insert"? Commented Sep 19, 2016 at 6:37
  • 4
    why not b[?:?, ?:?] = a? That is slice a matching block of b as place to put a Commented Sep 19, 2016 at 6:39
  • Do you want to insert a in the centre of b or a corner or somewhere else? Do you pad the other elements with 0 or leave them unchanged? Can you give an example of a and b and the resulted array? Commented Sep 19, 2016 at 6:51
  • @trincot Whoops, b should actually be np.zeros. Also, the padding should ideally be centered, but the top left corner is also good. Commented Sep 19, 2016 at 7:38

3 Answers 3

9

What about :

b[:a.shape[0],:a.shape[1]] = a

Note I assumed a is to be placed at the begining of b but you could refine it a bit to put a anywhere:

a0,a1=1,1
b[a0:a0+a.shape[0],a1:a1+a.shape[1]] = a
Sign up to request clarification or add additional context in comments.

Comments

2

More generally you can determine the position where you want to insert the array if you create a tuple of slices (this works for arbitary dimensions):

>>> a = np.random.random((5,5))
>>> b = np.ones((3,3))

>>> edge_coordinate = (0,0)
>>> slicer = tuple(slice(edge, edge+i) for edge, i in zip(edge_coordinate, b.shape))
>>> a[slicer] = b
>>> a
array([[ 1.        ,  1.        ,  1.        ,  0.14206495,  0.36385016],
       [ 1.        ,  1.        ,  1.        ,  0.08861402,  0.7888898 ],
       [ 1.        ,  1.        ,  1.        ,  0.1975496 ,  0.13345192],
       [ 0.550487  ,  0.22471952,  0.47050879,  0.04669643,  0.13480528],
       [ 0.25139511,  0.06499812,  0.42247189,  0.05840351,  0.74735495]])

by varying the edge_coordinate you can vary the position:

>>> a = np.random.random((5,5))
>>> b = np.ones((3,3))

>>> edge_coordinates = (1,1)  # changed
>>> slicer = tuple(slice(edge, edge+i) for edge, i in zip(edge_coordinates, b.shape))
>>> a[slicer] = b
>>> a
array([[ 0.21385714,  0.68789872,  0.3915475 ,  0.67342566,  0.05642307],
       [ 0.19778658,  1.        ,  1.        ,  1.        ,  0.70717406],
       [ 0.73678924,  1.        ,  1.        ,  1.        ,  0.90285997],
       [ 0.39709332,  1.        ,  1.        ,  1.        ,  0.96959814],
       [ 0.89627195,  0.21295355,  0.72598992,  0.80749348,  0.76660287]])

Ideally one could make a function of it - if you regularly use it.

2 Comments

But isn't this fancy indexing, which in general creates a new array? I just want to get a view of a previously-allocated-array and write to it.
@étale-cohomology No, a tuple of slices is regular indexing and returns a view.
0

I think the best way is to use padding.

if you want to place a in the top left corner:

np.pad(a,((0,5),(0,4)),'constant') 

if you want to place a in centre:

np.pad(a,((2,3),(2,2)),'constant')

1 Comment

But is this the fastest and most natural way? Doesn't this create a new array on the fly (which I'd rather not do)?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.