У меня есть 2D- numpy
массив. Есть ли способ создать на нем представление, которое включало бы первыеk
строки и все столбцы?
Дело в том, чтобы избежать копирования базовых данных (массив настолько велик, что создание частичных копий невозможно).
Ответы:
Конечно, просто проиндексируйте его как обычно. Например, y = x[:k, :]
это вернет представление в исходный массив. Никакие данные не будут скопированы, а любые обновления, внесенные в, y
будут отражены x
и наоборот.
Редактировать:
Я обычно работаю с 3D-массивами uint8 размером более 10 ГБ, поэтому я очень беспокоюсь об этом ... Numpy может быть очень эффективным в управлении памятью, если вы помните несколько вещей. Вот несколько советов, как избежать копирования массивов в памяти:
Используйте +=
, -=
, *=
и т.д. , чтобы избежать создания копии массива. Например x += 10
, модифицирует массив на месте, а x = x + 10
сделает копию и изменит его. (также посмотрите numexpr )
Если вы действительно хотите сделать копию x = x + 10
, имейте в виду, что x = x + 10.0
это приведет x
к автоматическому преобразованию в массив с плавающей запятой, если это еще не было. Однако, x += 10.0
где x
- целочисленный массив, вызовет10.0
массивом, вместо этого к преобразованию в тип int той же точности, что и у массива.
Кроме того, многие функции numpy принимают out
параметр, поэтому вы можете делать такие вещи, как np.abs(x, x)
получение абсолютного значения x
на месте.
В качестве второго редактирования, вот еще несколько советов по просмотрам и копиям с множественными массивами:
В отличие от списков Python, y = x[:]
он не возвращает копию, а возвращает представление. Если вам нужна копия (которая, конечно, удвоит объем используемой вами памяти), используйтеy = x.copy()
Вы часто слышите о "причудливой индексации" numpy массивов. Использование списка (или целочисленного массива) в качестве индекса - это «причудливая индексация». Это может быть очень полезно, но копирует данные.
В качестве примера: y = x[[0, 1, 2], :]
возвращает копию, а y = x[:3,:]
возвращает представление.
Даже действительно сумасшедшая индексация, такая как x[4:100:5, :-10:-1, None]
«нормальная» индексация, тем не менее, вернет представление, поэтому не бойтесь использовать всевозможные уловки нарезки для больших массивов.
x.astype(<dtype>)
вернет копию данных как новый тип, а x.view(<dtype>)
вернет представление.
Однако будьте осторожны ... Он чрезвычайно мощный и полезный, но вам нужно понимать, как основные данные хранятся в памяти. Если у вас есть массив чисел с плавающей запятой и вы рассматриваете их как целые числа, (или наоборот) numpy будет интерпретировать базовые биты массива как целые числа.
Например, это означает, что 1.0
64-битное число с плавающей запятой в системе с прямым порядком байтов будет 4607182418800017408
рассматриваться как 64-битное целое число, а массив - [ 0, 0, 0, 0, 0, 0, 240, 63]
как uint8. Это действительно хорошо, когда вам нужно выполнить какое-то изменение битов на больших массивах, хотя ... У вас есть низкоуровневый контроль над тем, как интерпретируется буфер памяти.
b
есть взгляд a
, то b.base is a
будет True
. Копия (любого массива) всегда будетarr_copy.base is None
x[np.array([1, 1, 3, 1])] += 1
измененx
. Теперь понял!