Home > Software engineering >  Numpy: How to stack a single array into each row of a bigger array and turn it into a 2D array?
Numpy: How to stack a single array into each row of a bigger array and turn it into a 2D array?

Time:06-09

I have a numpy array named heartbeats with 100 rows. Each row has 5 elements.

I also have a single array named time_index with 5 elements. I need to prepend the time index to each row of heartbeats.

heartbeats = np.array([
    [-0.58, -0.57, -0.55, -0.39, -0.40],
    [-0.31, -0.31, -0.32, -0.46, -0.46]
])
time_index = np.array([-2, -1, 0, 1, 2])

What I need:

array([-2, -0.58],
      [-1, -0.57],
      [0, -0.55],
      [1, -0.39],
      [2, -0.40],
      [-2, -0.31],
      [-1, -0.31],
      [0, -0.32],
      [1, -0.46],
      [2, -0.46])

I only wrote two rows of heartbeats to illustrate.

CodePudding user response:

Assuming you are using numpy, the exact output array you are looking for can be made by stacking a repeated version of time_index with the raveled version of heartbeats:

np.stack((np.tile(time_index, len(heartbeats)), heartbeats.ravel()), axis=-1)

CodePudding user response:

Another approach, using broadcasting

In [13]: heartbeats = np.array([
    ...:     [-0.58, -0.57, -0.55, -0.39, -0.40],
    ...:     [-0.31, -0.31, -0.32, -0.46, -0.46]
    ...: ])
    ...: time_index = np.array([-2, -1, 0, 1, 2])

Make a target array:

In [14]: res = np.zeros(heartbeats.shape   (2,), heartbeats.dtype)

In [15]: res[:,:,1] = heartbeats     # insert a (2,5) into a (2,5) slot

In [17]: res[:,:,0] = time_index[None]   # insert a (5,) into a (2,5) slot

In [18]: res
Out[18]: 
array([[[-2.  , -0.58],
        [-1.  , -0.57],
        [ 0.  , -0.55],
        [ 1.  , -0.39],
        [ 2.  , -0.4 ]],

       [[-2.  , -0.31],
        [-1.  , -0.31],
        [ 0.  , -0.32],
        [ 1.  , -0.46],
        [ 2.  , -0.46]]])

and then reshape to 2d:

In [19]: res.reshape(-1,2)
Out[19]: 
array([[-2.  , -0.58],
       [-1.  , -0.57],
       [ 0.  , -0.55],
       [ 1.  , -0.39],
       [ 2.  , -0.4 ],
       [-2.  , -0.31],
       [-1.  , -0.31],
       [ 0.  , -0.32],
       [ 1.  , -0.46],
       [ 2.  , -0.46]])

[17] takes a (5,), expands it to (1,5), and then to (2,5) for the insert. Read up on broadcasting.

CodePudding user response:

As an alternative way, you can repeat time_index by np.concatenate based on the specified times:

repeated_times = heartbeats.size // time_index.size      # 2
concatenated = np.concatenate([time_index] * repeated_times)
# [-2 -1  0  1  2 -2 -1  0  1  2]

# result = np.dstack((concatenated, heartbeats.reshape(-1))).squeeze()
result = np.array([concatenated, heartbeats.reshape(-1)]).T

Using np.concatenate may be faster than np.tile. This solution is faster than Mad Physicist, but the fastest is using broadcasting as hpaulj's answer.

  • Related