在numpy 1.6中引入的迭代器对象nditer提供了许多灵活的方式来以系统的方式访问一个或多个数组的所有元素。

1 单数组迭代

该部分位于numpy-ref-1.14.5第1.15 部分Single Array Iteration。

利用nditer对象可以实现完成访问数组中的每一个元素这项最基本的功能,使用标准的python迭代器接口可以逐个访问每一个元素。

1.1 默认迭代顺序

a = np.arange(6).reshape(2,3)
b = a.T
print(a)
# [[0 1 2]
#  [3 4 5]]
for i in np.nditer(a):
    print(i)
# 1 2 3 4 5 6(节约版面,竖着 -> 横着)
print(b)
# [[0 3]
#  [1 4]
#  [2 5]]
for j in np.nditer(b):
    print(j)
# 1 2 3 4 5 6(节约版面,竖着 -> 横着)
 

注意:通过该种方式迭代输出的是以元素在存储器中的布局顺序输出的,无论其视图做何种改变(转置,变换shape),其输出结果是一致的,该中方式可以提高迭代效率

1.2 控制迭代顺序 Controlling Iteration Order

有时候我们不去考虑元素在存储器中的位置关系,而需要按照特定顺序(如视图顺序)访问数组中的元素,nditer对象提供了一个命令参数来控制迭代输出顺序;

nditer 默认是‘K',也即order = ’K‘,该默认值为按在存储器中的顺序输出(keep the existing order),默认迭代顺序。

同时 nditer 中还提供了两个参数以控制迭代器输出顺序

- order = ‘ C ’ 按行访问

for x in np.nditer(a.T, order='C')

等价于

for x in np.nditer(a.T.copy(order='C'))

- order = ' F ' 按列访问

for x in np.nditer(a.T, order='F')

等价于

for x in np.nditer(a.T.copy(order='F'))

注意:虽然等价,当时其原理是不一样的,

(1)A和A.T的元素以相同的顺序遍历,即它们存储在存储器中的顺序,而A.T.拷贝的元素(order=‘C’)以不同的顺序被访问,因为它们被放入不同的存储器布局中。

(2)order = ’C‘ / ’F‘ 只是输出顺序改变了。

1.3 修改数组值(Modify Array Values)

一般情况下,python中的常规赋值只需要更变本地变量或全局变量字典中的引用,而不必修改现有变量。

默认情况下,nditer对象将输入数组视为只读对象,要修改数组中的元素,必须指定读写read-write 或只写write-only 模式,这是用每个操作数标志(per-operand flags )来控制的。

a = np.arange(6).reshape(2,3)
print(a)
# [[0 1 2]
#  [3 4 5]]
for x in np.nditer(a ,op_flags=['readwrite']):
    x[...] = 2 * x
print(a)
# [[ 0  2  4]
#  [ 6  8 10]]

如果不添加 op_flags=['readwrite'] ,则 ValueError: assignment destination is read-only ,所以必须添加readwrite;

一般是从数组元素中引用x,将其转换为所赋值的引用,而不会再将所赋值放入数组元素中;可以简单理解为可以从数组中取出元素并对元素值进行赋值运算,但是不能将计算后的值再放入数组中,如果要实现修改数组中的元素,x应该用省略号索引

注意:

a = np.arange(6).reshape(2,3)
print(a)
# [[0 1 2]
#  [3 4 5]]

for i in np.nditer(a ,op_flags=['readwrite']):
    i = i * 2
print(a)  #a值不发生改变
# [[0 1 2]
#  [3 4 5]]

for j in np.nditer(a ,op_flags=['readwrite']):
    j *= 2
print(a)  #a值均*2
# [[ 0  2  4]
#  [ 6  8 10]]

疑惑:按照语法规则,i = i *2 等价于 i *=2 ,为什么结果却不一样!有知道的请留言说一下,谢谢!

参考:python nditer---迭代数组

2 数组迭代(Iterating over arrays)

该部分内容位于numpy-ref-1.14.5中的3.15.4 Iterating over arrays 章节

numpy.nditer 为高效多维迭代器对象,用于对数组的迭代。

flags:sequence of str ,optional

用于控制迭代器行为的标志(flags)

buffrered - 再需要时可以缓冲

c_index - 跟踪C顺序的索引

f_index - 跟踪F顺序的索引

multi_index - 跟踪 多指标,或每个迭代维度的一组指数

external_loop - 外部循环,将一维的最内层的循环转移到外部循环迭代器,使得numpy的矢量操作在处理更大规模数据时变得更有效率。

op_flags:list of list of str , optional

这是每个操作数的标志列表。至少必须指定一个“只读”、“读写”或“写”。

readonly - 该操作数表明可以读取

readwrite - 该操作数表明可以读取和写入

writeonly - 该操作数表明仅写入

no_broadcast - 该操作数可以防止被广播

copy - 该操作数表明允许临时只读拷贝

op_dtypes:dtype or tuple of dtype(s), optional

操作数所需的数据类型(s)。

order:{‘C’, ‘F’, ‘A’, ‘K’}, optional

控制迭代顺序(Controls the iteration order)

2.1 使用外部循环 external_loop

将一维的最内层的循环转移到外部循环迭代器,使得numpy的矢量化操作在处理更大规模数据时变得更有效率。

a = np.arange(6).reshape(2,3)
print(a)
# [[0 1 2]
#  [3 4 5]]
for x in np.nditer(a, flags = ['external_loop']):
    print(x)
# [0 1 2 3 4 5]

for x in np.nditer(a, flags = ['external_loop'],order = 'C'):
    print(x)
# [0 1 2 3 4 5]

for x in np.nditer(a, flags = ['external_loop'],order = 'F'):
    print(x)
# [0 3]
# [1 4]
# [2 5]

面试题:面试题:将矩阵旋转90度,这道题写完之后,非常有成就感!

2.2 追踪单个索引或多重索引

a = np.arange(6).reshape(2,3)
print(a)
# [[0 1 2]
#  [3 4 5]]
it = np.nditer(a,flags = ['f_index'])

while not it.finished:
    print("%d <%d>" % (it[0], it.index))
    it.iternext()

# 0 <0>
# 1 <2>
# 2 <4>
# 3 <1>
# 4 <3>
# 5 <5>

为了更清楚地表述,可以直观地看下表

flags = multi_index

a = np.arange(6).reshape(2,3)
print(a)
# [[0 1 2]
#  [3 4 5]]
it = np.nditer(a,flags = ['multi_index'])

while not it.finished:
    print("%d <%s>" % (it[0], it.multi_index))
    it.iternext()
# 0 <(0, 0)>
# 1 <(0, 1)>
# 2 <(0, 2)>
# 3 <(1, 0)>
# 4 <(1, 1)>
# 5 <(1, 2)>

multi_index是将元素的行列位置以元组方式打印出来,但元组形式不是整型,所以要将 %d 变为 %s,

若不改,则会报错 TypeError: %d format: a number is required, not tuple

a = np.arange(6).reshape(1,2,3)
print(a)
# [[[0 1 2]
#   [3 4 5]]]
it = np.nditer(a,flags = ['multi_index'])

while not it.finished:
    print("%d <%s>" % (it[0], it.multi_index))
    it.iternext()
# 0 <(0, 0, 0)>
# 1 <(0, 0, 1)>
# 2 <(0, 0, 2)>
# 3 <(0, 1, 0)>
# 4 <(0, 1, 1)>
# 5 <(0, 1, 2)>

2.3 广播迭代

如果两个数组是 可广播的,nditer组合对象能够同时迭代它们,假设数组 a 具有维度 3*4 ,并且存在维度为 1*4的另一个数组b,则使用以下类型的迭代器(数组b被广播到a的大小)

a = np.arange(0,60,5).reshape(3,4)
print(a)
# [[ 0  5 10 15]
#  [20 25 30 35]
#  [40 45 50 55]]
b = np.array([1,  2,  3,  4], dtype = int)
print(b)
# [1 2 3 4]
for x,y in np.nditer([a,b]):
    print("%d:%d" %(x,y))
# 0:1
# # 5:2
# # 10:3
# # 15:4
# # 20:1
# # 25:2
# # 30:3
# # 35:4
# # 40:1
# # 45:2
# # 50:3
# # 55:4

参考:NumPy - 数组上的迭代nditer —— numpy.ndarray 多维数组的迭代python nditer---迭代数组、numpy-ref-1.14.5官方文档(1.5 Iterating Over Arrays )。

numpy 数组迭代Iterating over arrays的更多相关文章

  1. NumPy 数组迭代

    章节 Numpy 介绍 Numpy 安装 NumPy ndarray NumPy 数据类型 NumPy 数组创建 NumPy 基于已有数据创建数组 NumPy 基于数值区间创建数组 NumPy 数组切 ...

  2. 8、numpy——数组的迭代

    1.单数组的迭代 NumPy 迭代器对象 numpy.nditer 提供了一种灵活访问一个或者多个数组元素的方式. 迭代器最基本的任务的可以完成对数组元素的访问. 1.1 默认迭代顺序 import ...

  3. NumPy 数组切片

    章节 Numpy 介绍 Numpy 安装 NumPy ndarray NumPy 数据类型 NumPy 数组创建 NumPy 基于已有数据创建数组 NumPy 基于数值区间创建数组 NumPy 数组切 ...

  4. NumPy 数组创建

    章节 Numpy 介绍 Numpy 安装 NumPy ndarray NumPy 数据类型 NumPy 数组创建 NumPy 基于已有数据创建数组 NumPy 基于数值区间创建数组 NumPy 数组切 ...

  5. Numpy数组对象的操作-索引机制、切片和迭代方法

    前几篇博文我写了数组创建和数据运算,现在我们就来看一下数组对象的操作方法.使用索引和切片的方法选择元素,还有如何数组的迭代方法. 一.索引机制 1.一维数组 In [1]: a = np.arange ...

  6. Numpy 数组操作

    Numpy 数组操作 Numpy 中包含了一些函数用于处理数组,大概可分为以下几类: 修改数组形状 翻转数组 修改数组维度 连接数组 分割数组 数组元素的添加与删除 修改数组形状 函数 描述 resh ...

  7. 玩转NumPy数组

    一.Numpy 数值类型 1.前言:Python 本身支持的数值类型有 int(整型, long 长整型).float(浮点型).bool(布尔型) 和 complex(复数型).而 Numpy 支持 ...

  8. 操作 numpy 数组的常用函数

    操作 numpy 数组的常用函数 where 使用 where 函数能将索引掩码转换成索引位置: indices = where(mask) indices => (array([11, 12, ...

  9. NumPy 超详细教程(1):NumPy 数组

    系列文章地址 NumPy 最详细教程(1):NumPy 数组 NumPy 超详细教程(2):数据类型 NumPy 超详细教程(3):ndarray 的内部机理及高级迭代 文章目录 Numpy 数组:n ...

随机推荐

  1. oauth2-server-php-docs 授权类型

    授权码 概观 在Authorization Code交付式时使用的客户端想要请求访问受保护资源代表其他用户(即第三方).这是最常与OAuth关联的授予类型. 详细了解授权码 用例 代表第三方来电 履行 ...

  2. C++ 纯虚方法

    1.纯虚方法解决什么样的问题,为什么要设计出纯虚方法? 考虑下面的需求,基类声明了一个方法,这个方法只针对具体的子类才有意义,比如Animal的Eat()方法,调用Animal的Eat方法是没有意义的 ...

  3. Socket 编程IO Multiplexing

     Linux Socket 编程中I/O Multiplexing 主要通过三个函数来实现:select, poll,epoll来实现.I/O Multiplexing,先构造一张有关描述符的列表,然 ...

  4. .net部署时常见问题

    站点提示“不允许的父路径”怎么办 error: 40 - Could not open a connection to SQL Server解决办法 无法识别的属性“targetFramework”. ...

  5. git 保存用户名密码

    打开本地的.git/config 加入 [credential] helper = store 保存,第一次需要输入用户名密码,输入一次密码后第二次就会记住密码了不会再提示输入用户名及密码

  6. Jenkins知识地图

    转自:http://blog.csdn.net/feiniao1221/article/details/10259449 这篇文章大概写于三个月前,当时写了个大纲列表,但是在CSDN上传资源实在不方便 ...

  7. MDX Step by Step 读书笔记(九) - Working with Time 处理时间

    开篇介绍 这一章节主要用到的 MDX 函数: PeriodsToDate( [Level , [Member]] ) - 从指定级别的范围内,返回与指定成员同一级别,从第一个期间开始到指定成员结束的期 ...

  8. 基于TQ2440开发板的WiFi模块的使用经验总结

    一.软.硬件资源准备: 内核版本:linux-2.6.30.4 交叉编译器版本:4.3.3 wpa_supplicant工具:wpa_supplicant-0.7.3.tar ; openssl-0. ...

  9. SQL Server从BAK文件还原新的数据库

    同一个数据库多个副本 很多时候,比如为了方便测试,排查问题,我们常常会拿到问题系统的数据库备份来开发环境下debug,这个时候就会出现同一个数据库的多个副本. 还原法 还原到一个新建的空数据库,在选项 ...

  10. hibernate和struts实现分页

    仓促把功能进行实现一下  类与类之间也没有进行MVC式分开  重要的是逻辑 记录一下 希望其中的些许代码逻辑对你有用 TUserDaoImpl---dao层的实现 package com.pers.h ...