从numpy数组中获取第n个元素

时间:2017-06-26 12:16:58

标签: python arrays numpy

假设我有一个看似如下的rgb-imagetype:

d = [ [ [0, 1, 2],    [3, 4, 5],    [6 ,7 ,8] ], 
      [ [9, 10, 11], [12, 13, 14], [15, 16 ,17] ],
      [ [18,19, 20], [21, 22, 23], [24, 25 ,26] ] ]

我使用random

选择一些随机的r / g或b像素
import random
r = random.sample(range(1, len(d)*len(d[0])*3), 3)
# for example r = [25, 4, 15]

如何选择我想要的数据?

就像我希望25th value in array d代表r_value = 25的第一个d[2][2][1]一样,因为它是第25个值。

5 个答案:

答案 0 :(得分:2)

您要做的是将其索引为flat或1d数组。有很多方法可以做到这一点。 ravelreshape(-1)创建了1d视图,flatten()创建了1d副本。

效率最高的是flat迭代器(属性,而不是方法):

In [347]: d.flat[25]
Out[347]: 25

(它也可以在作业中使用,例如。d.flat[25]=0

In [341]: idx = [25, 4, 15]
In [343]: d.flat[idx]
Out[343]: array([25,  4, 15])

要找出3d索引是什么,有效用,unravel_index(以及相应的ravel_multi_index

In [344]: fidx=np.unravel_index(idx,d.shape)
In [345]: fidx
Out[345]: 
(array([2, 0, 1], dtype=int32),
 array([2, 1, 2], dtype=int32),
 array([1, 1, 0], dtype=int32))
In [346]: d[fidx]
Out[346]: array([25,  4, 15])

这个元组,一个元素的索引被“向下”读取,例如(2,2,1)。

在大型数组上,flat索引实际上要快一点:

In [362]: dl=np.ones((100,100,100))
In [363]: idx=np.arange(0,1000000,40)
In [364]: fidx=np.unravel_index(idx,dl.shape)
In [365]: timeit x=dl[fidx]
1000 loops, best of 3: 447 µs per loop
In [366]: timeit x=dl.flat[idx]
1000 loops, best of 3: 312 µs per loop

答案 1 :(得分:1)

如果您要频繁地线性检查/更改阵列,可以构建线性视图

d_lin = d.reshape(-1)  # construct a 1d view
d_lin[25]         # access the 25-th element

或者把它全部放在一个单行中:

d.reshape(-1)[25]  # construct a 1d view

您可以从现在开始访问(和修改)d_view中的元素作为1d数组。因此,您使用d_lin[25]访问第25个值。每次要访问/修改元素时,都不必构建新视图:只需重用d_lin视图。

此外,可以指定展平的顺序order='C'(类C),order='F'(类Fortran)或order='A'(Fortran-wise)如果在meory中连续,C-like否则))。 order='F'表示我们首先迭代最大维度。

视图的优势(但这也可能导致意外行为)是,如果您通过d_lin分配新值,例如 d_lin[25] = 3,它将改变原始矩阵

备选方案是.flatnp.ravel。所以以下几点是等价的:

d.reshape(-1)[25]
np.ravel(d)[25]
d.flat[25]

reshape(..)ravel(..)方法与flat方法之间存在一些差异。最重要的一点是d.flat 创建完整视图。实际上,如果我们想要将视图传递给另一个需要numpy数组的函数,那么它会崩溃,例如:

>>> d.flat.sum()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'numpy.flatiter' object has no attribute 'sum'
>>> d.reshape(-1).sum()
351
>>> np.ravel(d).sum()
351

这不是本身的问题。如果我们想限制工具的数量(例如作为保护机制),那么这实际上会给我们更多的安全性(尽管我们仍然可以批量设置元素元素,并在{{np.sum(..)上调用flatiter 1}} object)。

答案 2 :(得分:0)

您可以使用numpy.flatten方法,如下所示:

a = np.array(d)
d[25] # print 26

答案 3 :(得分:-1)

如果您只关心该值,则可以展平您的阵列,并直接以

的形式访问它
val = d.flatten()[r]

如果你真的想要与扁平索引相对应的索引,你需要这样的东西:

ix_2 = r % d.shape[2]
helper_2 = (r - ix_2) / d.shape[2]
ix_1 = helper_2 % d.shape[1]
helper_1 = (helper_2 - ix_1) / d.shape[1]
ix_0 = helper_1 % d.shape[0]

val = d[ix_0, ix_1, ix_2]

答案 4 :(得分:-1)

假设您不想展平您的阵列: 如果您事先知道子列表的大小,则可以轻松计算出来。在您的示例中,主列表的每个元素都是一个包含3个元素的列表,每个元素包含3.因此,要访问n,您可以执行类似

的操作

i = n//9 j = (n%9)//3 k = (n%3) element = d[i][j][k]

对于n=25,您可以按照自己的意愿获得i = 2, j = 2, k = 1

在python2中,您可以(并且必须)使用普通/运算符而不是//