简体   繁体   中英

Numpy indexed array insertion

I have 2 arrays, with the same shape on the last axis, ie:

First:

   [[6614, 3390, 6327, 7595, 2797],
   [4604, 3392, 4128, 1835, 7397],
   [2268,  367, 7595, 2268, 2546],
   [5450, 5450, 2836, 5450, 4106],
   [8846, 8846, 3666, 8846, 3098],
   [  -1,   -1, 5450,   -1, 5450],
   [  -1,   -1, 8846,   -1, 8846],
   [   0,    0,    0,    0,    0],
   [   0,    0,    0,    0,    0],
   [   0,    0,    0,    0,    0]]

Second:

   [[4035, 4035, 4035, 1168, 3545],
   [8846, 8846, 8846, 8846, 8846],
   [  -1,   -1,   -1, 8846,   -1]]

So let's say the shapes are (10,5) and (3,5). What I would like to do is insert the second array into the first one along the first axes, but have it so that each row of the first continues with the second array, ie: (I've denoted <<>> for elements of the second array)

   [[6614,      3390,     6327,      7595,         2797],
   [4604,       3392,     4128,      1835,         7397],
   [2268,       367,      7595,      2268,         2546],
   [5450,       5450,     2836,      5450,         4106],
   [8846,       8846,     3666,      8846,         3098],
   [<<4035>>,   <<4035>>, 5450,      <<1168>>,     5450],
   [<<8846>>,   <<8846>>, 8846,      <<8846>>,     8846],
   [<<-1>>,     <<-1>>,   <<4035>>,  <<8846>>, <<3545>>],
   [   0,       0,        <<8846>>,     0,     <<8846>>],
   [   0,       0,         <<-1>>,      0,       <<-1>>]]

Consider that there will always be enough space in the first array, and that additionally I also have a list of indices at which to insert the second array:

[5, 5, 7, 5, 7]

np.insert seems to not accept setting sequences at specific indices, so I would need something that accepts ranges to be set. This can be solved with for loops obviously, but I am thinking there is a simpler solution.

If you don't mind converting to a pandas DataFrame, here is a simple solution:

# Convert arrays to DataFrames
df1 = pd.DataFrame(first)
df2 = pd.DataFrame(second)

# Concatenate the first and second DataFrames
df = pd.concat([df1.replace([-1, 0], np.nan), df2])

df = df.apply(lambda x: pd.Series(x.dropna().values)).fillna(0).astype('int')

# Convert back to numpy array
df = df.as_matrix()

print(df)

[[6614 3390 6327 7595 2797]
 [4604 3392 4128 1835 7397]
 [2268  367 7595 2268 2546]
 [5450 5450 2836 5450 4106]
 [8846 8846 3666 8846 3098]
 [4035 4035 5450 1168 5450]
 [8846 8846 8846 8846 8846]
 [  -1   -1 4035 8846 3545]
 [   0    0 8846    0 8846]
 [   0    0   -1    0   -1]]

There might be a more efficient way to do it, but here goes.

The problem is easier to understand if you transpose your matrices first :

[[6614 4604 2268 5450 8846   -1   -1    0    0    0]
 [3390 3392  367 5450 8846   -1   -1    0    0    0]
 [6327 4128 7595 2836 3666 5450 8846    0    0    0]
 [7595 1835 2268 5450 8846   -1   -1    0    0    0]
 [2797 7397 2546 4106 3098 5450 8846    0    0    0]]

[[4035 8846   -1]
 [4035 8846   -1]
 [4035 8846   -1]
 [1168 8846 8846]
 [3545 8846   -1]]

You then simply need to write the second rows at the right offset :

import numpy as np
a = np.array([[6614, 3390, 6327, 7595, 2797],
               [4604, 3392, 4128, 1835, 7397],
               [2268,  367, 7595, 2268, 2546],
               [5450, 5450, 2836, 5450, 4106],
               [8846, 8846, 3666, 8846, 3098],
               [  -1,   -1, 5450,   -1, 5450],
               [  -1,   -1, 8846,   -1, 8846],
               [   0,    0,    0,    0,    0],
               [   0,    0,    0,    0,    0],
               [   0,    0,    0,    0,    0]])

b = np.array([[4035, 4035, 4035, 1168, 3545],
   [8846, 8846, 8846, 8846, 8846],
   [  -1,   -1,   -1, 8846,   -1]])

a2 = a.T
b2 = b.T

n = len(b2[0])

for i, offset in enumerate([5, 5, 7, 5, 7]):
  a2[i,offset:offset+n] = b2[i]

print(a2.T)

It outputs:

[[6614 3390 6327 7595 2797]
 [4604 3392 4128 1835 7397]
 [2268  367 7595 2268 2546]
 [5450 5450 2836 5450 4106]
 [8846 8846 3666 8846 3098]
 [4035 4035 5450 1168 5450]
 [8846 8846 8846 8846 8846]
 [  -1   -1 4035 8846 3545]
 [   0    0 8846    0 8846]
 [   0    0   -1    0   -1]]

You can also avoid the transposing forth and back:

import numpy as np

a = np.array([[6614, 3390, 6327, 7595, 2797],
               [4604, 3392, 4128, 1835, 7397],
               [2268,  367, 7595, 2268, 2546],
               [5450, 5450, 2836, 5450, 4106],
               [8846, 8846, 3666, 8846, 3098],
               [  -1,   -1, 5450,   -1, 5450],
               [  -1,   -1, 8846,   -1, 8846],
               [   0,    0,    0,    0,    0],
               [   0,    0,    0,    0,    0],
               [   0,    0,    0,    0,    0]])

b = np.array([[4035, 4035, 4035, 1168, 3545],
   [8846, 8846, 8846, 8846, 8846],
   [  -1,   -1,   -1, 8846,   -1]])

n = b.shape[0]

for i, offset in enumerate([5, 5, 7, 5, 7]):
  a[offset:offset+n, i] = b[:,i]

print(a)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM