如何对NumPy数组进行迭代

426 阅读6分钟

问题的提出和解决方案概述

在这篇文章中,你将学习如何使用Python对一维、二维和三维NumPy数组进行迭代。

使用NumPy库时,你会遇到需要遍历一维、二维甚至三维数组的情况。这篇文章将告诉你如何完成这项任务。


💬 问题:我们如何编写代码来遍历一个一维、二维或三维 NumPy数组?

我们可以通过以下方法之一来完成这项任务。

  • 方法1:使用一个 For 循环和 np.array()
  • 方法2:使用一个[`For`](https://blog.finxter.com/python-loops/)循环和 np.nditer()
  • 方法3:使用一个[`For`](https://blog.finxter.com/python-loops/)循环和 itertools
  • 方法4:使用一个 While循环和 np.size
  • 方法5:使用一个 [`For`](https://blog.finxter.com/python-loops/)循环和 np.ndenumerate()
  • 方法6:使用一个 [`For`](https://blog.finxter.com/python-loops/) 循环和 range()
  • 奖励:CSV到 np.array()

准备工作

在前进之前,请确保NumPy库已经安装。

然后,在每个脚本的顶部添加以下代码。这段代码将使本文中的代码能够无误运行。

import numpy as np 

导入NumPy库后,通过调用简码(np)来引用这个库。


方法1:使用For Loop和np.array()

这个方法使用一个 For 循环与 np.array()来遍历一个1D NumPy数组。在这个例子中,周期表中的前五(5)个原子数 被生成并显示

atomic_els = np.array(np.arange(1,6))

for el in atomic_els:
    print(el, end=' ')

以上,调用 np.array()函数,并传递给它 np.arange(1,6)两个参数:开始位置为一(1),停止位置为五(5)或(stop-1)。结果是一个由整数组成的数组 ,并保存到atomic_els

[1 2 3 4 5]

接下来,一个 For循环被实例化,遍历一维 NumPy数组的每个元素 `atomic_els`.

输出被发送到终端的一(1)行,因为一个额外的参数被传递到打印语句(end=' ')。这个参数用一个空格代替了默认的换行符

1 2 3 4 5

方法2:使用For Loop和nditer()

这个方法使用了一个[](https://blog.finxter.com/for-else-and-while-else-in-python-a-helpful-guide/)``[`for`](https://blog.finxter.com/python-loops/)``循环与[`np.nditer()`](https://numpy.org/doc/stable/reference/generated/numpy.nditer.html)来遍历一个NumPy数组。在这个例子中,显示周期表中的前五(5)个原子数中子数 数据。

atomic_data = np.array([np.arange(1,6), [0, 2, 4, 5, 6]])

for dim in atomic_data:
    for d in dim:
        print(d, end=' ')

以上,调用 np.array()函数,并将[`np.arange(1,6)`](https://blog.finxter.com/numpy-arange/)作为第一个参数,第二个参数是相关的 中子数数组。

接下来,一个外部 for循环被实例化了。这是对每个数组维度的迭代。

在这个循环中,另一个 for循环被实例化。里面的循环遍历上述维度的每个元素。

输出被发送到终端的一(1)行上,作为附加参数被传递给打印语句(end=' ')。这个参数用一个空格代替了默认的换行符。

1 2 3 4 5 0 2 4 5 6

💡注意:第一个尺寸被高亮显示,以方便区分尺寸。


方法3:使用For Loop和itertools

这个方法使用一个 ``[`for`](https://blog.finxter.com/python-loops/)``循环和Python的内置 itertools库来遍历一个NumPy数组。在这个例子中,显示周期表中的前三(3)个原子数相位群组 数据。

import itertools 
  
atomic_num = np.arange(1,4)
atomic_phase = ['gas', 'gas', 'solid']
atomic_group = [1, 18, 1]
  
for (a, b, c) in itertools.zip_longest(atomic_num, atomic_phase, atomic_group, fillvalue=0):
    print (a, b, c)

以上,导入 itertools库来使用 zip_longest()函数。

然后,声明三(3)个数组,包含周期表中前三(3)个元素的相关数据。它们分别保存在atomic_num,atomic_phase, 和atomic_group

接下来,一个 ``[`for`](https://blog.finxter.com/python-loops/)``循环被实例化,并在大括号内传递三(3)个参数(a, b, c) ,这些参数参考了zip_longest(atomic_num, atomic_phase, atomic_group) 函数内的参数。

一个额外的参数(fillvalue=0)也被传递。这将为不等长的列表填补任何缺失的数值,并注明数值。

该循环一直迭代到数组的末端,每次迭代都向终端输出。

1 gas 1
2 gas 18
3 solid 1

方法4:使用While循环和尺寸

这个方法使用一个 while循环与``[`np.size`](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.size.html)``来遍历一个NumPy数组。在这个例子中,显示周期表中的前五(5)个原子数中子数相位 数据。

atomic_names = np.array(['Hydrogen', 'Helium', 'Lithium', 'Beryllium', 'Boron'])
el_count = 0

while el_count < atomic_names.size:
    print(atomic_names[el_count], end=' ')
    el_count += 1

以上,调用 np.array()函数,并传递一个包含周期表前五(5)个元素名称的列表。这些结果保存到atomic_names

然后,声明一个变量,el_count ,其起始值为零 (0)。这将是一个计数器变量,让 While循环知道何时停止迭代。

接下来,一个 while循环被实例化,并通过atomic_names 中的元素进行迭代。当el_count 的值仍然小于atomic_names.size 的值时,这个循环将继续进行。

作为一个额外的参数传递给打印语句(end=' '),输出被发送到终端的一(1)行上。这个参数用一个空格代替了默认的换行符。

Hydrogen Helium Lithium Beryllium Boron

方法5:使用For Loop和np.ndenumerate()。

这个方法使用一个 [`For`](https://blog.finxter.com/python-loops/)循环和 np.ndenumerate()来遍历一个NumPy数组。在这个例子中,显示的是元素周期表的前五(5)个元素名称

atomic_names = np.array(['Hydrogen', 'Helium', 'Lithium', 'Beryllium', 'Boron'])

for idx, x in np.ndenumerate(atomic_names):
    print(idx, x)

以上,调用 np.array()函数,并传递给它一个包含周期表中前五(5)个元素名称的数组。结果保存到atomic_names

接下来,一个 ``[`for`](https://blog.finxter.com/python-loops/)``循环被实例化,引用idx ,这是数组的索引,以及x ,这是数组元素的值。

输出被发送到终端。然后idx ,显示一个 Tuple包含数组的索引值,然后是每次迭代的x 的值。

(0,) Hydrogen
(1,) Helium
(2,) Lithium
(3,) Beryllium
(4,) Boron

方法6:使用For Loop和range()。

这个方法使用了一个 [`for`](https://blog.finxter.com/python-loops/)循环和 range())来迭代一个三维NumPy数组。

nums = np.array([[[1, 2],   [3, 4],   [5, 6]],
                  [[7, 8],   [9, 10],  [11, 12]],
                  [[13, 14], [15, 16], [17, 18]],
                  [[19, 20], [21, 22], [23, 23]],
                  [[24, 25], [26, 27], [28, 29]]])

for x in range(0, 5):
    for y in range(0, 3):
        for z in range(0, 2):
            print(nums[x][y][z])

上面声明了一个3D NumPy数组,包含1-29(含)的连续数字。这些保存到nums

接下来,三(3)个 [`for`](https://blog.finxter.com/python-loops/)循环被实例化,以循环并向终端输出nums 的内容,每行一(1)个数字。

每个循环的range()函数都是基于3D Numpy数组的尺寸,比如说。

  • 第一个循环(range(0,5)确定了数组中的弓箭手的总数。

  • 下一个循环(range(0,3)确定了数组中的列数。

  • 最后一个循环(range(0,2)确定数组中每一列的元素。

最后,输出被发送到终端(只有片段)。

1
2
3
4
5
6
7
8
9
10
...

奖励:将CSV转换成np.array()

这个例子以CSV文件的形式读入周期表的一个片段。这个数据被转换为NumPy数组并输出到终端。

下面的CSV文件包含了元素周期表中前七(7)种元素的原子序数原子质量中子数电子数的数值。

内容pt_sample.csv

1,1.007,0
2,4.002,2
3,6.941,4
4,9.012,5
5,10.811,6
6,12.011,6
7,14.007,7

为了继续学习,请将此文件保存为pt_sample.csv ,并将其移至当前工作目录。

import pandas as pd
import csv

file_name = 'pt_sample.csv'
df_data = np.array(list(csv.reader(open(file_name, 'r'), delimiter=','))).astype("float")
print(df_data)

以上,导入潘达斯库和CSV库。这是与DataFrames一起工作和读入CSV文件所需要的。

然后,声明一个文件名并保存到file_name

在突出显示的一行中,调用 np.array()函数被调用并传递以下参数。

  • 的函数作为一个参数,这个参数传递了,以读取( )模式打开指定的CSV文件。 [csv.reader()](https://blog.finxter.com/python-convert-csv-to-_-8-different-target-formats/)函数作为一个参数,这个参数传递给open() 方法,以读取(r)模式打开指定的CSV文件,包括field 分隔符(csv.reader(open(file_name, 'r'), delimiter=','))。
  • CSV文件的内容转换为一个列表
  • 这个列表转换为一个 np.array().

结果保存到df_data ,并输出到终端。

[[ 1. 1.007 0. ]
[ 2. 4.002 2. ]
[ 3. 6.941 4. ]
[ 4. 9.012 5. ]
[ 5. 10.811 6. ]
[ 6. 12.011 6. ]
[ 7. 14.007 7. ]]

总结

这(7)种NumPy数组的迭代方法应该给你足够的信息来选择最适合你编码要求的方法。

祝您好运,编码愉快!