English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Итерация массива NumPy

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

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

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

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

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

Исходный массив такой:
[[ 0 1 2 3 4 5]]
 [ 6 7 8 9 10 11]]
Итеративный вывод элементов массива такой:
0 1 2 3 4 5 6 7 8 9 10 11

В этом примере не используется стандартный C или Fortran порядок, выбранный порядок соответствует памяти массива, это делается для повышения эффективности доступа, по умолчанию это приоритет строк (row-major order, или C-order).

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

import numpy as np
a = np.arange(12).reshape(2,6)
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=" ")

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

0 1 2 3 4 5 6 7 8 9 10 11 
0 6 1 7 2 8 3 9 4 10 5 11

Из вышеуказанных примеров可以看出, a и a.T имеют одинаковый порядок итерации, то есть они хранятся в памяти в одинаковой последовательности, но a.T.copy(order = 'C') результат итерации будет разным, так как он differs от первых двух методов хранения, по умолчанию это доступ по строкам.

контроль порядка итерации

for x in np.nditer(a, order='F'): Fortran order, то есть приоритет столбцов:for x in np.nditer(a.T, order='C'): C order, то есть приоритет строк:

import numpy as np
a = np.arange(0, 100, 5)
a = a.reshape(4, 5)
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 60 65 70]
 [75 80 85 90 95]
Транспонированный массив:
[[ 0 25 50 75]
 [ 5 30 55 80]
 [10 35 60 85]
 [15 40 65 90]
 [20 45 70 95]
Сортировка по стилю C:
[[ 0 25 50 75]
 [ 5 30 55 80]
 [10 35 60 85]
 [15 40 65 90]
 [20 45 70 95]
0 25 50 75 5 30 55 80 10 35 60 85 15 40 65 90 20 45 70 95 
Сортировка по стилю F:
[[ 0 25 50 75]
 [ 5 30 55 80]
 [10 35 60 85]
 [15 40 65 90]
 [20 45 70 95]
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95

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

import numpy as np
a = np.arange(0, 100, 5)
a = a.reshape(4, 5)
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 60 65 70]
 [75 80 85 90 95]
Сортировка по стилю C:
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 
Сортировка по стилю F:
0 25 50 75 5 30 55 80 10 35 60 85 15 40 65 90 20 45 70 95

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

У объекта nditer есть еще один опциональный параметр op_flags. По умолчанию nditer рассматривает массив, который необходимо итерировать, как только чтение объекта (read-only), чтобы изменить значения элементов массива в процессе итерации, необходимо указать режим read-write или write-only.

import numpy as np
a = np.arange(0, 100, 5)
a = a.reshape(4, 5)
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 60 65 70]
 [75 80 85 90 95]
Измененный массив составляет:
[[0 10 20 30 40]
 [0 10 20 30 40]
 [100 110 120 130 140]
 [150 160 170 180 190]

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

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

ПараметрОписание
c_indexМожет отслеживать индекс C-порядка
f_indexМожет отслеживать индекс Fortran-порядка
multi-indexКаждый итерационный процесс может отслеживать один тип индекса
external_loopПредоставленные значения представляют собой одномерный массив с несколькими значениями, а не нулевым массивом

В следующем примере итератор проецируется на соответствующие столбцы и комбинируется в одномомерный массив.

import numpy as np
a = np.arange(0, 100, 5)
a = a.reshape(4, 5)
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 60 65 70]
 [75 80 85 90 95]
Измененный массив составляет:
[0 25 50 75] [5 30 55 80] [10 35 60 85] [15 40 65 90] [20 45 70 95]

Бroadcasting итерация

Если два массива являются广播имыми, объект комбинации 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,