#python #numpy #matrix
#питон #тупица #матрица
Вопрос:
Общую проблему, с которой я сталкиваюсь, можно перевести следующим образом:
Кодируйте матрицу NxN, в которой регулярно чередуются подматрицы mxm значений x или y.
Например, допустим, мне нужно сделать матрицу 6×6 с 2×2 подматрицами 0 или 1, чередующимися, результатом должна быть матрица ниже:
0 0 1 1 0 0 0 0 1 1 0 0 1 1 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 0 0 1 1 0 0
На данный момент мне удалось получить только это:
0 0 1 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
с помощью кода :
b = numpy.zeros((6, 6)) b[:2, 2:6:4] = 1 b[2:6:4, :2] = 1 print(b)
Мне удалось найти решение, но оно имеет четыре цикла, поэтому его трудно прочитать и занимает немного времени. Код для этого возможного ответа таков:
c = np.array([]) for k in range(3): for l in range (2): for i in range(3): for j in range (2): if (k i)%2 == 0: c = np.append(c, 0) else: c = np.append(c, 1) print("c = ", np.reshape(c, (6, 6)))
Разве нет лучшего способа получить ожидаемый результат без использования циклов или с максимальным количеством циклов 1 или 2 ?
Ответ №1:
import numpy as np m = 8 n = 4 c = np.zeros(shape=(m,m)) assert not m%n #m must be divisible by n for row_i in range(m): for col_i in range(m): if (row_i//n col_i//n)%2: c[row_i][col_i] = 1 print(c)
[[0. 0. 0. 0. 1. 1. 1. 1.] [0. 0. 0. 0. 1. 1. 1. 1.] [0. 0. 0. 0. 1. 1. 1. 1.] [0. 0. 0. 0. 1. 1. 1. 1.] [1. 1. 1. 1. 0. 0. 0. 0.] [1. 1. 1. 1. 0. 0. 0. 0.] [1. 1. 1. 1. 0. 0. 0. 0.] [1. 1. 1. 1. 0. 0. 0. 0.]]
Ответ №2:
Я думаю, что вы на правильном пути с использованием нарезки массивов python. Вот пример для подматриц 2×2 (работает с любой матрицей b четного квадратного размера).
# first block for submatrices starting at column and row index 0 # 0::4 - every 4th column/row starting from column 0 # so this results in 1 0 0 0 1 0 and so on b[0::4, 0::4] = 1 # 1::4 - every 4th column starting from column 1 # so this results in 0 1 0 0 0 1 and so on b[0::4, 1::4] = 1 b[1::4, 0::4] = 1 b[1::4, 1::4] = 1 # second block for submatrices starting from column and row index 2 b[2::4, 2::4] = 1 b[2::4, 3::4] = 1 b[3::4, 2::4] = 1 b[3::4, 3::4] = 1
Теперь для больших подматриц вам нужно просто увеличить расстояние между записями. Для подматриц размера n
расстояние должно быть 2 * n
таким , потому что это схема для повторения 1
в матрице. Затем каждый блок имеет размер n
. Попробуйте написать процедуру. Если у вас не получится, я буду помогать и дальше.
Ответ №3:
Я сократил ваш цикл до 2:
def create_mxm_from_NxN(N,m): """N has to be divisible by m""" b = np.zeros((N,N)) skip = N // m for i in range(0,N 1,m): for s in range(1,skip 1,2): b[i:i m, i s*m:i (s 1)*m] = 1 b[i s*m:i (s 1)*m, i:i m] = 1 return b.astype(int)
Выход:
create_mxm_from_NxN(6,2) [[0 0 1 1 0 0] [0 0 1 1 0 0] [1 1 0 0 1 1] [1 1 0 0 1 1] [0 0 1 1 0 0] [0 0 1 1 0 0]] create_mxm_from_NxN(9,3) [[0 0 0 1 1 1 0 0 0] [0 0 0 1 1 1 0 0 0] [0 0 0 1 1 1 0 0 0] [1 1 1 0 0 0 1 1 1] [1 1 1 0 0 0 1 1 1] [1 1 1 0 0 0 1 1 1] [0 0 0 1 1 1 0 0 0] [0 0 0 1 1 1 0 0 0] [0 0 0 1 1 1 0 0 0]]
Ответ №4:
Вот один из вариантов использования np.repeat
и np.tile
:
import numpy as np def tiled_matrix(n, m): row = np.tile(np.repeat([1, 0], m), (n // m) // 2 1)[:n] row_block = np.tile(row, (m,1)) two_rows_block = np.vstack((row_block, 1 - row_block)) arr = np.tile(two_rows_block, ((n // m) // 2 1, 1))[:n] return arr print(tiled_matrix(10, 4)) # [[1 1 1 1 0 0 0 0 1 1] # [1 1 1 1 0 0 0 0 1 1] # [1 1 1 1 0 0 0 0 1 1] # [1 1 1 1 0 0 0 0 1 1] # [0 0 0 0 1 1 1 1 0 0] # [0 0 0 0 1 1 1 1 0 0] # [0 0 0 0 1 1 1 1 0 0] # [0 0 0 0 1 1 1 1 0 0] # [1 1 1 1 0 0 0 0 1 1] # [1 1 1 1 0 0 0 0 1 1]]
Вот еще один дубль с np.meshgrid
и xor
:
def meshgrid_mod(n, m): ix = np.arange(n, dtype=np.uint8) xs, ys = np.meshgrid(ix, ix) arr = ((xs % (2*m)) lt; m) ^ ((ys % (2*m)) lt; m) return arr.astype(np.int)
Ответ №5:
Самое простое решение, вероятно, состоит в том, чтобы использовать skimage.util.view_as_blocks()
:
import numpy as np import skimage.util a = np.zeros((6, 6)) b = skimage.util.view_as_blocks(a, (2, 2)) # b is a view of a, so changing values in b will also change values in a b[::2, ::2, ...] = 1 b[1::2, 1::2, ...] = 1 a # array([[1., 1., 0., 0., 1., 1.], # [1., 1., 0., 0., 1., 1.], # [0., 0., 1., 1., 0., 0.], # [0., 0., 1., 1., 0., 0.], # [1., 1., 0., 0., 1., 1.], # [1., 1., 0., 0., 1., 1.]])