Подсчитайте и найдите шаблон в 2D массиве в python - PullRequest
1 голос
/ 09 апреля 2020

У меня есть эти данные ниже:

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

Я хочу подсчитать, сколько 0 в каждой строке и количество для каждого 0 рядом друг с другом. В результате я надеялся получить новый массив, подобный этому:

[[1 2 1 2]
 [2 1 2 1]
 [2 2 1 2]
 [2 5 2]]

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

так что я найду 212, или 424, или 636, или 9 5 10 (допустимо), и т. д. c

ожидаемый результат:

[[0,6],[1,5],[2,7]]

это позиции каждого 1 в 212 массива data массива

Я пробовал с этим кодом ниже:

np.unique(data, return_counts=True, axis=1)

Я возился с этим, и результат оказался не таким, как я ожидал. Это используется для обработки изображений, и данные были огромными

Ответы [ 2 ]

2 голосов
/ 09 апреля 2020
data = np.array([[1, 0,-1, 0, 0, 1, 0,-1, 0, 0, 1],
                 [1, 1, 0, 0,-1, 0, 1, 0, 0,-1, 0],
                 [1, 0, 0, 1, 0, 0,-1, 0, 1, 0, 0],
                 [0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0]])
a = data

Подсчет последовательных нулей в каждой строке:
Numpy и Python l oop (s).
Итерация по строкам; найти индексы нулей; разбить строку, где индексы отличаются более чем на один; получить формы результата.

for row in a:
    zeros = np.where(row==0)[0]
    neighbors = (np.argwhere(np.diff(zeros)>1)+1).ravel()
    w = np.split(zeros,neighbors)
    counts = [thing.shape[0] for thing in w]
    print(counts)

Индексы шаблона:
Использует некоторое вещание - работает со всеми строками за один раз при выполнении итерации по столбцам

# pattern to search for:
# notzero,zero,zero,notzero,zero,notzero,zero,zero,notzero
pattern = np.array([False,True,True,False,True,False,True,True,False])    

# find zeros in data and pad
padded = np.pad(a==0,1)
dif = padded.shape[1] - pattern.shape[0]
for i in range(dif+1):
    stop = i+pattern.shape[0]
    test = padded[:,i:stop]
    equal =  test == pattern
    equal = np.all(equal,1)
    if any(equal):
        row = np.argwhere(equal).ravel()[0]
        print(f'[{row-1},{i+3}]')

Это должно найти несколько ( разделенных и перекрывающихся) шаблонов подряд - похоже, работает с:

data = np.array([[1, 0,-1, 0, 0, 1, 0,-1, 0, 0, 1, 0,-1, 0, 0, 1,-1, 0, 0, 1, 0,-1, 0, 0],
                 [1, 1, 0, 0,-1, 0, 1, 0, 0,-1, 0, 1, 0, 0,-1, 0, 0, 0,-1, 0, 1, 0, 0,-1],
                 [1, 0, 0, 1, 0, 0,-1, 0, 1, 0, 0,-1, 0, 1, 0, 0, 0, 1, 0, 0,-1, 0, 1, 0],
                 [0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0]])
1 голос
/ 09 апреля 2020

Адаптация ответа @jezrael из cumsum со сбросом и при условии, что вы можете добавить зависимость pandas:

import pandas as pd
import numpy as np

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

df = pd.DataFrame(data.T, columns=range(data.shape[0]))
a = (df == 0)
df = a.cumsum()-a.cumsum().where(~a).ffill().fillna(0).astype(int)

# Add a last row of zeros 
df.loc[len(df)] = 0

# Define custom function to apply column-wise
def find_pattern(col):
    c = col.to_numpy()
    ids = np.argwhere(c==0) - 1 
    ids = ids[ids>=0]
    return [x for x in c[ids] if x!=0]

r = df.apply(lambda col: find_pattern(col), axis=0)

r
0    [1, 2, 1, 2]
1    [2, 1, 2, 1]
2    [2, 2, 1, 2]
3       [2, 5, 2]
dtype: object

Результат r представляет собой серию pandas индексируется по индексу строки и ожидаемому результату в виде значений.

Наконец, чтобы найти шаблон [2,1,2], вы можете снова использовать функции pandas:

r = pd.DataFrame(r, columns=['zeros'])
r['string_col'] = r['zeros'].apply(lambda row: ''.join([str(x) for x in row]))

pattern_as_string = '212'
r['pattern_index'] = r['string_col'].str.find(pattern_as_string)

         zeros  string_col  pattern_index
0  [1, 2, 1, 2]       1212              1
1  [2, 1, 2, 1]       2121              0
2  [2, 2, 1, 2]       2212              1
3     [2, 5, 2]        252             -1

Где pattern_index значение, с которого начинается шаблон, и его -1, если он не найден.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...