2

I'm trying to broadcast the contents of one array into another array like this:

A = np.array([[1, 3], [2, 4]])
A_broadcast = np.array([[1, 0, 3, 0], [0, 2, 0, 4], [1, 2, 3, 4]])

My current approach is by initializing A_broadcast with np.zeros((3, 4)) and slicing the contents of A into A_broadcast one line at a time like this:

A_broadcast[::2][0] = A[0]
A_broadcast[1::2][1] = A[1]
A_broadcast[::2][2] = A[0]
A_broadcast[1::2][2] = A[1]

But I get this error: ValueError: could not broadcast input array from shape (2,) into shape (4,) This approach works in Matlab so I thought something similar would work here. Is there a way this approach can work? If not, what could I do to get a similar effect?

  • 4
    You have the index order wrong. `A_broadcast[0][::2] = A[0]` or in one go `A_broadcast[0,::2] = A[0]` – Julien Aug 08 '23 at 00:13
  • often it's a good idea to test the LHS by itself.. `A_broadcast[::2][0]` what's that shape? The error says (4,)? The ::2 selects everyother row, that is 2: (2,4). The [0] selects one of those, hence (4,). – hpaulj Aug 08 '23 at 01:02
  • Thank you @Julien! Oops, such a simple error. – E. V. Hadzen Aug 08 '23 at 14:52

2 Answers2

3

Your current approach can be improved by using NumPy's array manipulation and broadcasting capabilities. Here's a more efficient way to achieve the desired result:

import numpy as np

A = np.array([[1, 3], [2, 4]])
rows, cols = A.shape

# Create a mask to insert zeros at appropriate positions
mask = np.zeros((rows * 2, cols * 2), dtype=bool)
mask[::2, ::2] = True

# Create the broadcasting array with zeros
A_broadcast = np.zeros((rows * 2, cols * 2))

# Use the mask to assign values from array A to A_broadcast
A_broadcast[mask] = A.flatten()

print("Original Array A:")
print(A)
print("Broadcasted Array A_broadcast:")
print(A_broadcast)

This code creates a mask that will insert values from array A at the specified positions in A_broadcast. It then flattens A and uses the mask to assign the values to the corresponding positions in the broadcasting array. The result is the desired broadcasting effect.

Here's the output:

Original Array A:
[[1 3]
 [2 4]]
Broadcasted Array A_broadcast:
[[1. 0. 3. 0.]
 [0. 2. 0. 4.]
 [1. 0. 3. 0.]
 [0. 2. 0. 4.]]

This approach avoids the need for separate assignments for each row and uses broadcasting efficiently to achieve the desired result.

1

Your 2 arrays:

In [86]: A = np.array([[1, 3], [2, 4]])
    ...: A_broadcast = np.array([[1, 0, 3, 0], [0, 2, 0, 4], [1, 2, 3, 4]])
  
In [88]: A
Out[88]: 
array([[1, 3],
       [2, 4]])

In [89]: A_broadcast
Out[89]: 
array([[1, 0, 3, 0],
       [0, 2, 0, 4],
       [1, 2, 3, 4]])

the blank:

In [87]: res = np.zeros((3,4),int)

The first row of A goes into a square that alternates in both directions:

In [90]: res[::2,::2]=A[0]

In [91]: res
Out[91]: 
array([[1, 0, 3, 0],
       [0, 0, 0, 0],
       [1, 0, 3, 0]])

Actually I wasn't sure if A[0] was right its (2,1) version. I could have analzed the case, but instead just tried it. Sometimes in an interactive session it's easier to try a few alternatives than to carefully work out the details in my head before hand. It's easy to experient in an interactive session with modules like numpy.

Now it's easy to do the same with the 2nd row,

In [92]: res[1:,1::2]=A[1]

In [93]: res
Out[93]: 
array([[1, 0, 3, 0],
       [0, 2, 0, 4],
       [1, 2, 3, 4]])

Nothing wrong with indexing the target one row at a time as you attempt:

In [94]: res[0,::2]
Out[94]: array([1, 3])

In [95]: res[2,1::2]
Out[95]: array([2, 4])

Both rows could also be indexed with advanced indexing - we just have to get the broadcasting right, using a (2,1), and (2,) arrays (or list equivalents):

In [96]: res[[[0],[2]],[0,2]]
Out[96]: 
array([[1, 3],
       [1, 3]])

In [97]: res[[[1],[2]],[1,3]]
Out[97]: 
array([[2, 4],
       [2, 4]])
hpaulj
  • 221,503
  • 14
  • 230
  • 353