Как найти и сопоставить шаблоны в массиве Numpy? - PullRequest
1 голос
/ 08 апреля 2020

У меня большой массив с нулями и единицами, array = [1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1]. Как я могу найти подходящие шаблоны, такие как [0, 0], [0, 1], [1, 0], [1, 1] в массиве.

Ответы [ 2 ]

0 голосов
/ 08 апреля 2020

Для этого можно использовать свертку, например, numpy.convolve:

import numpy as np

data = np.array([1, 0, 1, 0, 0, 0, 0 ,1, 1, 0, 1, 1])

# this fixes the issue that some patterns look identical
# scores due to the multiplication with 0
# e.g. [1, 0, 1] and [1, 1, 1]
# we just replace the 0 by -1
data[data == 0] = -1


kernel = np.array([0, 0, 0, 1, 1, 0, 1, 1])

# same fix for kernel
kernel[kernel == 0] = -1

res = np.convolve(data,kernel, 'full')
print(res)
# >>> [-1  0 -1  2  1  2  5 -2 -2 -2 -2  0 -5 -2  5  0 -1  2  1]

res = np.convolve(data,kernel, 'same')
print(res)
# >>> [ 2  1  2  5 -2 -2 -2 -2  0 -5 -2  5]    

res = np.convolve(data,kernel, 'valid')
print(res)
# >>> [-2 -2 -2 -2  0]

Чем выше результат, тем лучше совпадение. В вашем случае это должно быть равно числу единиц в вашем шаблоне, и индекс можно найти с помощью np.argmax().

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

Существует также scipy.signal.convolve, что может быть быстрее, если вы обрабатываете много данных.

0 голосов
/ 08 апреля 2020

Вы можете использовать эту функцию для создания массива скользящего окна:

def rolling_window(a, window):
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)


arr = np.array([1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1])
pattern = np.array([1, 0, 1])

arr = rolling_window(arr, pattern.shape[0])
print(arr)

Вывод:

[[1 1 1]
 [1 1 0]
 [1 0 0]
 [0 0 0]
 [0 0 0]
 [0 0 1]
 [0 1 1]
 [1 1 0]
 [1 0 1]
 [0 1 1]]

Затем вы можете искать совпадения:

(arr == pattern).all(axis=1)
# [False False False False False False False False  True False]

Кроме того, вы можете использовать метод rolling в pandas:

(pd.Series(arr).rolling(pattern.shape[0])
    .apply(lambda x: (x == pattern).all())
    .fillna(0).astype('bool'))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...