假设我有一个看似如下的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
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个值。
答案 0 :(得分:2)
您要做的是将其索引为flat或1d数组。有很多方法可以做到这一点。 ravel
和reshape(-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
,它将改变原始矩阵强>
备选方案是.flat
或np.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中,您可以(并且必须)使用普通/
运算符而不是//