Перебор массивов NumPy

Объект итератора NumPy numpy.nditer предоставляет гибкий способ доступа к одному или нескольким элементам массива.

Самая базовая задача итератора — доступ к элементам массива.

Далее мы используем функцию arange() для создания массива 2X3 и применяем nditer для итерации по нему.

Пример

import numpy as np a = np.arange(6).reshape(2,3) print ('Исходный массив:') print (a) print ('\n') print ('Итерация по элементам:') for x in np.nditer(a): print (x, end=", " ) print ('\n')

Результат вывода:

原始数组是:
[[0 1 2]
 [3 4 5]]


迭代输出元素:
0, 1, 2, 3, 4, 5, 

Приведённые выше примеры не используют стандартный порядок C или Fortran; выбранный порядок согласуется с размещением массива в памяти, чтобы повысить эффективность доступа. По умолчанию используется порядок по строкам (или C-порядок).

Это отражает, что по умолчанию каждый элемент просто доступен без учёта его конкретного порядка. Мы можем увидеть это, выполняя итерацию по транспонированному массиву из предыдущего примера и сравнивая её с методом copy, который обращается к транспонированному массиву в порядке C, как в следующем примере:

Пример

import numpy as np a = np.arange(6).reshape(2,3) for x in np.nditer(a.T): print (x, end=", " ) print ('\n') for x in np.nditer(a.T.copy(order='C')): print (x, end=", " ) print ('\n')

Результат вывода:

0, 1, 2, 3, 4, 5, 

0, 3, 1, 4, 2, 5, 

Как видно из приведённых выше примеров, порядок обхода a и a.T одинаков, что означает, что они также имеют одинаковый порядок хранения в памяти, ноa.T.copy(order = 'C')даёт другой результат обхода, потому что его способ хранения отличается от двух предыдущих, и по умолчанию доступ осуществляется по строкам.

Управление порядком обхода

  • for x in np.nditer(a, order='F'):Порядок Fortran, т. е. порядок по столбцам;
  • for x in np.nditer(a.T, order='C'):Порядок C, т. е. порядок по строкам;

Пример

import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) print ('Исходный массив:') print (a) print ('\n') print ('Транспонированный исходный массив:') b = a.T print (b) print ('\n') print ('В порядке C:') c = b.copy(order='C') print (c) for x in np.nditer(c): print (x, end=", " ) print ('\n') print ('В порядке F:') c = b.copy(order='F') print (c) for x in np.nditer(c): print (x, end=", " )

Результат вывода:

原始数组是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]


原始数组的转置是:
[[ 0 20 40]
 [ 5 25 45]
 [10 30 50]
 [15 35 55]]


以 C 风格顺序排序:
[[ 0 20 40]
 [ 5 25 45]
 [10 30 50]
 [15 35 55]]
0, 20, 40, 5, 25, 45, 10, 30, 50, 15, 35, 55, 

以 F 风格顺序排序:
[[ 0 20 40]
 [ 5 25 45]
 [10 30 50]
 [15 35 55]]
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55,

Вы можете заставить объект nditer использовать определённый порядок, явно задав его:

Пример

import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) print ('Исходный массив:') print (a) print ('\n') print ('В порядке C:') for x in np.nditer(a, order = 'C'): print (x, end=", " ) print ('\n') print ('В порядке F:') for x in np.nditer(a, order = 'F'): print (x, end=", " )

Результат вывода:

原始数组是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]


以 C 风格顺序排序:
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 

以 F 风格顺序排序:
0, 20, 40, 5, 25, 45, 10, 30, 50, 15, 35, 55,

Изменение значений элементов массива

Объект nditer имеет еще один необязательный параметр — op_flags. По умолчанию nditer рассматривает массив, по которому выполняется итерация, как объект только для чтения. Чтобы изменять значения элементов массива во время итерации по массиву, необходимо указать режим readwrite или writeonly.

Пример

import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) print ('Исходный массив:') print (a) print ('\n') for x in np.nditer(a, op_flags=['readwrite']): x[...]=2*x print ('Изменённый массив:') print (a)

Результат вывода:

原始数组是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]


修改后的数组是:
[[  0  10  20  30]
 [ 40  50  60  70]
 [ 80  90 100 110]]

Использование внешнего цикла

Конструктор класса nditer имеет параметр flags, который может принимать следующие значения:

Параметр Описание
c_index Может отслеживать индекс в порядке C
f_index Может отслеживать индекс в порядке Fortran
multi_index Может отслеживать один тип индекса за итерацию
external_loop Заданное значение — это одномерный массив с несколькими значениями, а не нульмерный массив

В приведённом ниже примере итератор проходит по каждому столбцу и объединяет их в одномерный массив.

Пример

import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) print ('Исходный массив:') print (a) print ('\n') print ('Изменённый массив:') for x in np.nditer(a, flags = ['external_loop'], order = 'F'): print (x, end=", " )

Результат вывода:

原始数组是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]


修改后的数组是:
[ 0 20 40], [ 5 25 45], [10 30 50], [15 35 55],

Итерация с вещанием

Если два массива совместимы для вещания, объект комбинирования nditer может перебирать их одновременно. Предположим, массив a имеет размеры 3X4, а массив b — размеры 1X4; тогда используется следующий итератор (массив b вещанием приводится к размеру a).

Пример

import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) print ('Первый массив:') print (a) print ('\n') print ('Второй массив:') b = np.array([1, 2, 3, 4], dtype = int) print (b) print ('\n') print ('Изменённый массив:') for x,y in np.nditer([a,b]): print ("%d:%d" % (x,y), end=", " )

Результат вывода:

第一个数组为:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]


第二个数组为:
[1 2 3 4]


修改后的数组为:
0:1, 5:2, 10:3, 15:4, 20:1, 25:2, 30:3, 35:4, 40:1, 45:2, 50:3, 55:4,
Другие расширения