Эффективный поиск строк в массиве с определенными условиями - PullRequest
1 голос
/ 09 июня 2019

У меня есть два numpy массива 2D.То, что я хочу сделать, это найти конкретные строки np_weight в np_sentence.

Например:

#rows are features, columns are clusters or whatever
np_weight = np.random.uniform(1.0,10.0,size=(7,4))
print(np_weight)

[[9.96859395 8.65543961 6.07429382 4.58735497]
 [3.21776471 8.33560037 2.11424961 8.89739975]
 [9.74560314 5.94640798 6.10318198 7.33056421]
 [6.60986206 2.36877835 3.06143215 7.82384351]
 [9.49702267 9.98664568 3.89140374 5.42108704]
 [1.93551346 8.45768507 8.60233715 8.09610975]
 [5.21892795 4.18786508 5.82665674 8.28397111]]

#rows are sentence index, columns are words on that sentence
np_sentence = np.random.randint(0.0,7.0,size=(5,3))
print(np_sentence)

[[2 5 1]
 [1 6 4]
 [0 0 0]
 [2 3 6]
 [4 2 4]]

Если я сортирую np_weight в каждом столбце, а затем получаюtop5 этого, у меня будет этот (здесь я просто показываю первый столбец) :

temp_sorted_result=
[9.96859395 ] --->index=0
[9.74560314 ] --→ index=2
[9.49702267 ] --→ index=4
[6.60986206 ] --->index=3
[5.21892795 ] --->index=6

Теперь я хочу найти эти индексы два по два во втором массиве numpynp_sentence чтобы увидеть, есть ли какая-либо строка в том, что содержит два индекса.

Например, на основании этого он должен вывести: 1,3,4.Это индексы np_sentence, которые включают комбинацию из двух индексов, например, temp_sorted_result.

, both 4 and 6, доступные в temp_sorted_result, находятся в той же строке np_sentence в row=1 и т. д.

Мне нужно сделать это для каждого столбца np_weight.Для меня очень важно иметь очень эффективный код, так как количество строк очень велико

На данный момент я выполнил поиск только одного элемента во втором массиве, что в конечном итоге не то, что мне нужно:

Одним из подходов может быть то, что я формирую все комбинации для каждого столбца, например, для первого столбца, показанного выше temp_sorted_result, я формирую

(0,2) (0,4)(0,3) (0,6)
(2,4) (2,3) (2,6)
(4,3)(4,6)
(3,6)

, а затем проверяю, какая из них доступна встроки np_sentence.База на моем np_sentence строках индекса 1,3,4 содержит некоторые из них.

Теперь мой вопрос заключается в том, как я могу реализовать это наиболее эффективным способом?

Пожалуйста, дайте мне знать, еслиэто не очевидно.

Я ценю вашу помощь:)

1 Ответ

1 голос
/ 09 июня 2019

Вот один из подходов: функция f ниже создает маску той же формы, что и weight (плюс один фиктивный ряд False с), помечая пять первых записей в каждом столбце True.

Затем он использует np_sentence для индексации в маске и считает True для каждого столбца, пары строк и сравнивает с пороговым значением два.

Единственное осложнение: мы должны исключить повторяющиеся значения в строках np_sentence. Для этого мы сортируем строки и затем направляем каждый индекс, равный его левому соседу, к фиктивной строке в маске.

Эта функция возвращает маску. Последняя строка скрипта демонстрирует, как преобразовать эту маску в индексы.

import numpy as np

def f(a1, a2, n_top, n_hit):
    N,M = a1.shape
    mask = np.zeros((N+1,M), dtype=bool)
    np.greater_equal(
        a1,a1[a1.argpartition(N-n_top, axis=0)[N-n_top], np.arange(M)],
        out=mask[:N])
    a2 = np.sort(a2, axis=1)
    a2[:,1:][a2[:,1:]==a2[:,:-1]] = N
    return np.count_nonzero(mask[a2], axis=1) >= n_hit

a1 = np.matrix("""[[9.96859395 8.65543961 6.07429382 4.58735497]
 [3.21776471 8.33560037 2.11424961 8.89739975]
 [9.74560314 5.94640798 6.10318198 7.33056421]
 [6.60986206 2.36877835 3.06143215 7.82384351]
 [9.49702267 9.98664568 3.89140374 5.42108704]
 [1.93551346 8.45768507 8.60233715 8.09610975]
 [5.21892795 4.18786508 5.82665674 8.28397111]]"""[2:-2].replace("]\n [",";")).A

a2 = np.matrix("""[[2 5 1]
 [1 6 4]
 [0 0 0]
 [2 3 6]
 [4 2 4]]"""[2:-2].replace("]\n [",";")).A

print(f(a1,a2,5,2))

from itertools import groupby
from operator import itemgetter

print([[*map(itemgetter(1),grp)] for k,grp in groupby(np.argwhere(f(a1,a2,5,2).T),itemgetter(0))])

Выход:

[[False  True  True  True]
 [ True  True  True  True]
 [False False False False]
 [ True False  True  True]
 [ True  True  True False]]
[[1, 3, 4], [0, 1, 4], [0, 1, 3, 4], [0, 1, 3]]
...