Расщепление матрицы с использованием массива индексов - PullRequest
0 голосов
/ 15 апреля 2019

У меня есть матрица, которую я хочу разделить на две части. Два новых типа запутаны, но у меня есть массивы «start» и «stop», указывающие, какие строки принадлежат каждой новой матрице.

Я привел небольшой пример ниже, включая мое собственное решение, которое я не нахожу удовлетворительным.

Есть ли более умный способ расщепления матрицы?

Обратите внимание, что в этом примере есть определенная периодичность, которая не в реальной матрице.

import numpy as np

np.random.seed(1)
a = np.random.normal(size=[20,2])
print(a)

b_start = np.array([0, 5, 10, 15])
b_stop = np.array([2, 7, 12, 17])

c_start = np.array([2, 7, 12, 17])
c_stop = np.array([5, 10, 15, 20])

b = a[b_start[0]:b_stop[0], :]
c = a[c_start[0]:c_stop[0], :]

for i in range(1, len(b_start)):
    b = np.append(b, a[b_start[i]:b_stop[i], :], axis=0)
    c = np.append(c, a[c_start[i]:c_stop[i], :], axis=0)

print(b)
print(c)

Ответы [ 2 ]

0 голосов
/ 15 апреля 2019

Поздравляем с правильным использованием np.append. У многих постеров с этим проблемы.

Но быстрее собрать значения в списке и выполнить одно объединение. np.append создает новый массив каждый раз; Добавление списка просто добавляет указатель на список на месте.

b = []
c = []
for i in range(1, len(b_start)):
    b.append(a[b_start[i]:b_stop[i], :])
    c.append(a[c_start[i]:c_stop[i], :])
b = np.concatenate(b, axis=0)
c = np.concatenate(c, axis=0)

или даже

b = np.concatenate([a[i:j,:] for i,j in zip(b_start, b_stop)], axis=0)

Другой ответ

idx = np.hstack([np.arange(i,j) for i,j in zip(b_start, b_stop)])
a[idx,:]

Исходя из предыдущих вопросов SO, я ожидаю, что два подхода будут иметь примерно одинаковую скорость.

0 голосов
/ 15 апреля 2019

Вы можете использовать причудливую функциональность индексации numpy.

index_b = np.array([np.arange(b_start[i], b_stop[i]) for i in range(b_start.size)])
index_c = np.array([np.arange(c_start[i], c_stop[i]) for i in range(c_start.size)])
b = a[index_b].reshape(-1, a.shape[1])
c = a[index_c].reshape(-1, a.shape[1])

Это даст вам тот же вывод.

Тестовый прогон:

import numpy as np

np.random.seed(1)
a = np.random.normal(size=[20,2])
print(a)

b_start = np.array([0, 5, 10, 15])
b_stop = np.array([2, 7, 12, 17])

c_start = np.array([2, 7, 12, 17])
c_stop = np.array([5, 10, 15, 20])

index_b = np.array([np.arange(b_start[i], b_stop[i]) for i in range(b_start.size)])
index_c = np.array([np.arange(c_start[i], c_stop[i]) for i in range(c_start.size)])
b = a[index_b].reshape(-1, a.shape[1])
c = a[index_c].reshape(-1, a.shape[1])
print(b)
print(c)

Выход:

[[ 1.62434536 -0.61175641]
 [-0.52817175 -1.07296862]
 [ 1.46210794 -2.06014071]
 [-0.3224172  -0.38405435]
 [-1.10061918  1.14472371]
 [ 0.90159072  0.50249434]
 [-0.69166075 -0.39675353]
 [-0.6871727  -0.84520564]]
[[ 0.86540763 -2.3015387 ]
 [ 1.74481176 -0.7612069 ]
 [ 0.3190391  -0.24937038]
 [ 1.13376944 -1.09989127]
 [-0.17242821 -0.87785842]
 [ 0.04221375  0.58281521]
 [ 0.90085595 -0.68372786]
 [-0.12289023 -0.93576943]
 [-0.26788808  0.53035547]
 [-0.67124613 -0.0126646 ]
 [-1.11731035  0.2344157 ]
 [ 1.65980218  0.74204416]]

Я сделал 100 запусков двух подходов, время выполнения:

0.008551359176635742#python for loop
0.0034341812133789062#fancy indexing

И 10000 пробегов:

0.18994426727294922#python for loop
0.26583170890808105#fancy indexing
...