Получить верхнюю матрицу инцидентов - PullRequest
1 голос
/ 28 октября 2019

У меня есть матрица, и у каждой строки / столбца есть номер (как известно, как инцидент), например:

    9  7  6
9 [[1, 2, 3],
7  [4, 5, 6],
6  [7, 8, 9]]

Я хочу получить инцидент верхней матрицы в двух списках, один для строк идругой для столбцов (потому что моя матрица симметрична). Например,

row = [9, 9, 9, 7, 7, 6]
col = [9, 7, 6, 7, 6, 6]

Я могу сделать это для строки с

import numpy as np

myIncidents = [9, 7, 6]
row = np.array(myIncidents).repeat(np.arange(len(myIncidents), 0, -1))  # [9, 9, 9, 7, 7, 6]

Но я не знаю, как этого добиться для col. Любой совет?

Ответы [ 2 ]

2 голосов
/ 28 октября 2019

Вот один способ с помощью masking получить оба значения: row и col -

def triu_elements(a):
    n = len(a)
    r1 = np.broadcast_to(a,(n,n))
    r2 = np.broadcast_to(a[:,None],(n,n))
    mask = ~np.tri(n,k=-1,dtype=bool)
    return r2[mask],r1[mask]

Пример выполнения -

In [56]: myIncidents = np.array([9,7,6])

In [57]: triu_elements(myIncidents)
Out[57]: (array([9, 9, 9, 7, 7, 6]), array([9, 7, 6, 7, 6, 6]))

Время: для различных наборов данных

Сравнение решений @Paul Panzer с np.triu_indices здесь.

Set # 1 (Small):

In [105]: Incidents = np.random.randint(0,100,(100))

# @Paul Panzer's solution-1
In [106]: %%timeit
     ...: rowID,colID = np.triu_indices(len(Incidents))
     ...: row,col = Incidents[rowID],Incidents[colID]
10000 loops, best of 3: 66.8 µs per loop

# @Paul Panzer's solution-2
In [116]: %timeit np.fromiter(it.chain.from_iterable(it.combinations_with_replacement(Incidents,2)),int).reshape(2,-1,order="F")
1000 loops, best of 3: 259 µs per loop

In [107]: %timeit triu_elements(Incidents)
10000 loops, best of 3: 38.3 µs per loop

Set # 2 (Large):

In [99]: Incidents = np.random.randint(0,100,(1000))

In [100]: %%timeit
     ...: rowID,colID = np.triu_indices(len(Incidents))
     ...: row,col = Incidents[rowID],Incidents[colID]
100 loops, best of 3: 6.24 ms per loop

In [101]: %timeit triu_elements(Incidents)
1000 loops, best of 3: 1.7 ms per loop

Комплект № 3 (очень большой):

In [121]: Incidents = np.random.randint(0,100,(10000))

In [122]: %%timeit
     ...: rowID,colID = np.triu_indices(len(Incidents))
     ...: row,col = Incidents[rowID],Incidents[colID]
1 loop, best of 3: 1.08 s per loop

In [123]: %timeit triu_elements(Incidents)
1 loop, best of 3: 421 ms per loop
1 голос
/ 28 октября 2019

Вы можете использовать triu_indices и расширенное индексирование:

Incidents = np.array([9,7,6])
row,col = np.triu_indices(len(Incidents))
row,col = Incidents[row],Incidents[col]

row
# array([9, 9, 9, 7, 7, 6])
col
# array([9, 7, 6, 7, 6, 6])

Для массивов малого и среднего размера itertools часто быстрее, чем numpy:

import itertools as it
np.fromiter(it.chain.from_iterable(it.combinations_with_replacement([9,7,6],2)),int).reshape(2,-1,order="F")
# array([[9, 9, 9, 7, 7, 6],
#        [9, 7, 6, 7, 6, 6]])
...