2

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.

5
  • Are you using numpy? Also, what happened to the second row? Commented Jun 8, 2022 at 17:02
  • The operation you are looking for is "concatenate" or "stack" in numpy terminology, not "merge" Commented Jun 8, 2022 at 17:02
  • "Pair" means "two elements". I think you meant "rows". Commented Jun 8, 2022 at 17:09
  • Please add a numpy tag and use np.... if you are using numpy. Otherwise, please indicate which array package you are using. Python does not support multidimensional arrays in the standard library. Commented Jun 8, 2022 at 17:10
  • Thanks for being responsive! It's a nice change from the usual "dump and walk away" approach some new users take. Commented Jun 8, 2022 at 17:15

3 Answers 3

2

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)
Sign up to request clarification or add additional context in comments.

1 Comment

@d.b. h.shape[0] is a good alternative, flatten is not because it copies the data unnecessarily, while ravel does not. It's rare that you want to use flatten over ravel. Also, doing the transpose will alter the layout of the array in memory over stacking on axis=-1.
2

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.

Comments

1

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

concatenated = np.concatenate([time_index] * heartbeats.shape[0])
# [-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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.