2016-10-24 2 views
2

Предположим, у меня есть матрица 4x4, которая выглядит следующим образом:NumPy: заполните поля, окружающие 1 в массиве

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

Я хочу, чтобы написать функцию, которая принимает все 4 окружающие поля одного и превращает их в 1.

выше матрица станет:

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

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

В матрице содержатся только 0 и 1. Если 1 находится на краю матрицы, то 1 не следует обертывать, т. Е. Если самое левое поле равно 1, самое правильное поле по-прежнему остается равным 0. Кроме того, я использую Python 3.5

Есть ли более математический или лаконичный способ сделать это?

+3

Что делать, если есть '2'? Что, если соседнее поле уже «1»? Есть только один '1'? Может ли это быть на «краю»? Что тогда, shoud это обернуть? – zvone

+0

Только что отредактировал исходное сообщение. Большое спасибо за ваш комментарий – Narusan

+0

Итак, для пограничных элементов у нас не будет 4 соседей, но 2 или 3 соседа. Итак, мы будем заполнять только 1 в этих? – Divakar

ответ

6

Это выглядит как бинарное расширение. Там есть функция доступна в SciPy, который реализует это эффективно:

>>> from scipy.ndimage import binary_dilation 
>>> x 
array([[0, 0, 0, 0], 
     [0, 0, 1, 0], 
     [0, 0, 0, 0], 
     [0, 0, 0, 0]]) 

>>> binary_dilation(x).astype(int) 
array([[0, 0, 1, 0], 
     [0, 1, 1, 1], 
     [0, 0, 1, 0], 
     [0, 0, 0, 0]]) 

1s по краям обрабатываются как вы указали, что они должны быть (т.е. без переноса).

См. documentation для получения дополнительных опций и аргументов.

1

FWIW, вот способ сделать это, просто используя Numpy. Мы вставляем исходные данные в строки & столбцов нулей, а затем побитовые или смещенные копии массива вместе.

import numpy as np 

def fill(data): 
    rows, cols = data.shape 
    padded = np.pad(data, 1, 'constant', constant_values=0) 
    result = np.copy(data) 
    for r, c in ((0, 1), (1, 0), (1, 2), (2, 1)): 
     result |= padded[r:r+rows, c:c+cols] 
    return result 

data = np.asarray(
    [ 
     [0, 0, 0, 0], 
     [0, 0, 1, 0], 
     [0, 0, 0, 0], 
     [0, 0, 0, 0], 
    ], dtype='uint8') 
print(data, '\n') 

result = fill(data) 
print(result) 

выход

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

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

Большое спасибо. По соображениям производительности я собираюсь использовать scipy-версию этой задачи, но здорово знать теорию этой функции – Narusan

Смежные вопросы