Копирование меньшего квадратного массива (m, m) из большего (n, n) в Python - PullRequest
0 голосов
/ 17 сентября 2018

Предположим, у меня есть массив:

from numpy import *
x = range(16)
x = reshape(x,(4,4))

print x
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]

И я хочу получить копию меньшего массива, который всегда центрирован в середине x, определив размер этой матрицы (неиндексы строки / столбца)

Например, если я хочу получить массив 2x2 из этого, он вернет:

[[5  6]
 [9 10]]

Для моих целей мой начальный массив больше (4096x4096), и я хочувозьмите копию массива среднего квадрата размеров (128x128), (256x256), (512x512), (1024x1024), (2048x2048).

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

Я думал об определении некоторых переменных, таких как (для 2x2case):

rows_to_keep = [1,2]
cols_to_keep = [1,2]

, а затем использовать

x[np.ix_(rows_to_keep, columns_to_keep)]

Но это становится непрактичным, когда my rows_to_keep представляет собой список из 2048 чисел, например, для копирования квадрата 128x128 из4096x4096 оригинал Я могу создать список индексов, который начинается в строке / столбце 1984и переходит к 2112:

size_to_keep = 128
indices = np.linspace(0, size_to_keep, size_to_keep, endpoint=False)

rows_to_keep = [(4096/2)-(size_to_keep/2) + i for i in indices]
cols_to_keep = [(4096/2)-(size_to_keep/2) + i for i in indices]

copy_array = x[np.ix_(rows_to_keep, columns_to_keep)]    

Но опять это становится грязным / непрактичным.Я надеялся, что есть более питонический способ сделать это?Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Numpy работает с представлениями , что означает, что когда вы делаете

extracted_middle_square = x[1:2,1:2]

вы получаете представление x (не копия, и x не изменяется). Если вы хотите создать новую переменную, выполните

extracted_middle_square = x[1:2,1:2].copy()

Это должно решить вашу проблему.

0 голосов
/ 17 сентября 2018

Поскольку все ваши индексы непрерывны, вы можете просто использовать соответствующие slice s. Очевидно, что вы не можете избежать вычисления экстремумов, но это все.

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

def get_center(arr, size):
    mask = tuple(
        slice(int(dim / 2 - size / 2), int(dim / 2 + size / 2))
        if 0 < size < dim else slice(None)
        for dim in arr.shape)
    return arr[mask].copy()

, который можно просто использовать как:

import numpy as np
dim = 4
x = np.arange(dim * dim).reshape((dim, dim))
y = get_center(x, 2)
# [[ 5,  6],
#  [ 9, 10]]

и работает как положено, но не занимая столько памяти.

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

...