python nditer---迭代数组

迭代对象nditer提供了一种灵活访问一个或者多个数组的方式。

单个数组的迭代(Single Array Iteration)

迭代器最基本的任务的可以完成对数组元素的访问,迭代器接口可以一个接一个地提供的每一个元素。

例如:

a = np.arange(6).reshape(2, 3)
for x in np.nditer(a):
    print x, " "
0  1  2  3  4  5  
对于这种迭代方式需要注意的是:所选择的顺序是和数组内存布局一致的,而不是使用标准C或者Fortran顺序。这是为了使用效率而设计的,这反映了默认情况下只需访问每个元素,而无需考虑其特定顺序。我们可以通过迭代上述数组的转置来看到这一点,并与以C顺序访问 数组转置的copy的方式做对比,有:

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

0 1 2 3 4 5 

0 3 1 4 2 5

从上述例子可以看出,a和a.T的遍历顺序是一样的,也就是他们在内存中的存储顺序也是一样的,但是a.T.copy(order = 'C')的遍历结果是不同的,那是因为它和前两种的存储方式是不一样的。默认是按行访问。

控制迭代顺序(Controlling Iteration Order)

有时候,无论元素在内存中的分布如何,重要的是要以特定的顺序来访问数组。所以nditer提供了一种顺序参数(order parameter 的方法来实现这一要求。默认情况下是order = 'K', 就是上述的访问方式。另外有:order = 'C'和order = 'F'。不妨理解为:C是按行访问,F是按列访问。

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

0 3 1 4 2 5 

0 3 1 4 2 5


修改数组值(Modify Array Values)
默认情况下,nditer将输入数组视为 只读对象。要修改数组元素,必须指定读写(  read-write)或只写( write-only)模式。这是由每个 操作数标志控制的。一般而言,Python中的赋值只需更改本地或全局变量字典中的引用,而不是修改现有变量。

a = np.arange(6).reshape(2, 3)
print a

for x in np.nditer(a, op_flags = ['readwrite']):
    x[...] = 2*x

print a

[[0 1 2]
 [3 4 5]]
[[ 0  2  4]
 [ 6  8 10]]


使用外部循环

  In all the examples so far, the elements of a are provided by the iterator one at a time, because all the looping logic is internal to the iterator. While this is simple and convenient, it is not very efficient. A better approach is to move the one-dimensional innermost loop into your code, external to the iterator. This way, NumPy’s vectorized operations can be used on larger chunks of the elements being visited.

  The nditer will try to provide chunks that are as large as possible to the inner loop. By forcing ‘C’ and ‘F’ order, we get different external loop sizes. This mode is enabled by specifying an iterator flag.

  Observe that with the default of keeping native memory order, the iterator is able to provide a single one-dimensional chunk, whereas when forcing Fortran order, it has to provide three chunks of two elements each.

a = np.arange(6).reshape(2, 3)

for x in np.nditer(a, flags = ['external_loop']):
    print x

for x in np.nditer(a, flags = ['external_loop'], order = 'F'):
    print x

[0 1 2 3 4 5]

[0 3]
[1 4]
[2 5]

跟踪单一索引或者多索引

  During iteration, you may want to use the index of the current element in a computation. For example, you may want to visit the elements of an array in memory order, but use a C-order, Fortran-order, or multidimensional index to look up values in a different array.

  The Python iterator protocol doesn’t have a natural way to query these additional values from the iterator, so we introduce an alternate syntax for iterating with an nditer. This syntax explicitly works with the iterator object itself, so its properties are readily accessible during iteration. With this looping construct, the current value is accessible by indexing into the iterator, and the index being tracked is the property index or multi_index depending on what was requested.

  The Python interactive interpreter unfortunately prints out the values of expressions inside the while loop during each iteration of the loop. We have modified the output in the examples using this looping construct in order to be more readable.

a = np.arange(6).reshape(2, 3)
it = np.nditer(a, flags = ['f_index'])
while not it.finished:
    print '%d<%d>' % (it[0], it.index),
    it.iternext()

print '\n'

it = np.nditer(a, flags = ['multi_index'])
while not it.finished:
    print '%d<%s>' % (it[0], it.multi_index),
    it.iternext()
    
print '\n'   

it = np.nditer(a, flags = ['multi_index'], op_flags = ['writeonly'])
while not it.finished:
    it[0] = it.multi_index[1] - it.multi_index[0]
    it.iternext()
print a

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

0<(0, 0)> 1<(0, 1)> 2<(0, 2)> 3<(1, 0)> 4<(1, 1)> 5<(1, 2)> 

[[ 0  1  2]
 [-1  0  1]]

单一索引的是按列顺序输出元素的下标,而多索引输出的是元素的坐标,比如元素3的坐标(1,0),不清晰,再看一下三维数组的多索引结果:

b = np.arange(27).reshape(3, 3, 3)
it = np.nditer(b, 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)> 
6<(0, 2, 0)> 7<(0, 2, 1)> 8<(0, 2, 2)> 9<(1, 0, 0)> 10<(1, 0, 1)> 11<(1, 0, 2)>
12<(1, 1, 0)> 13<(1, 1, 1)> 14<(1, 1, 2)> 15<(1, 2, 0)> 16<(1, 2, 1)> 
17<(1, 2, 2)> 18<(2, 0, 0)> 19<(2, 0, 1)> 20<(2, 0, 2)> 21<(2, 1, 0)> 
22<(2, 1, 1)> 23<(2, 1, 2)> 24<(2, 2, 0)> 25<(2, 2, 1)> 26<(2, 2, 2)>   


出处:https://docs.scipy.org/doc/numpy-1.10.0/reference/arrays.nditer.html



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值