Python 从numpy数组中获取第n个元素
假设我有一个rgb imagetype的numpy数组,如下所示:Python 从numpy数组中获取第n个元素,python,arrays,numpy,Python,Arrays,Numpy,假设我有一个rgb imagetype的numpy数组,如下所示: 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] ] ] ix_2 = r % d.shape[2] helper_2 = (r - ix_2) / d.shape[2] ix_1
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] ] ]
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]
a = np.array(d)
d[25] # print 26
我使用random
import random
r = random.sample(range(1, len(d)*len(d[0])*3), 3)
# for example r = [25, 4, 15]
然后如何选择所需的数据
就像我想要数组d中的第25个值对应于
d[2][2][1]
的第一个r_值=25
,因为它是第25个值。如果你只关心这个值,你可以展平你的数组,并直接访问它
val = d.flatten()[r]
如果确实需要与展平索引对应的索引,则需要执行以下操作:
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] ] ]
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]
a = np.array(d)
d[25] # print 26
如果要经常线性地检查/更改阵列,可以构建线性视图:
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_视图
中的元素作为1d数组进行访问(和修改)。因此,您可以使用d_lin[25]
访问第25个值。不必每次访问/修改元素时都构造一个新视图:只需重用dulin
视图即可
此外,可以指定展平的顺序(order='C'
(C-like)、order='F'
(Fortran-like)或order='A'
(Fortran-wise,如果在meory中连续,则为C-like))order='F'
意味着我们首先迭代最大维度
视图的优点(但这也可能导致意外行为)是,如果通过d_-lin
分配新值,如d_-lin[25]=3
,它将改变原始矩阵
替代方案是,或。因此,以下内容在某种程度上是等效的:
d.reshape(-1)[25]
np.ravel(d)[25]
d.flat[25]
然而,重塑(…)
和拉威尔(…)
方法与扁平
方法之间存在一些差异。最重要的一点是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
>d.flat.sum()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:'numpy.flatiter'对象没有属性'sum'
>>>d.重塑(-1).求和()
351
>>>np.ravel(d).sum()
351
这本身不是问题。如果我们想限制工具的数量(例如作为一种保护机制),那么这实际上会给我们带来更多的安全性(尽管我们仍然可以批量设置元素,并在
flatiter
对象上调用np.sum(..)
。您可以使用numpy.flatte
方法,如下所示:
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] ] ]
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]
a = np.array(d)
d[25] # print 26
假设您不想展平阵列: 如果您事先知道子列表的大小,就可以轻松地计算出来。在您的示例中,主列表的每个元素都是一个正好包含3个元素的列表,每个元素包含3个元素。因此,要访问
n
,您可以执行以下操作
i=n//9
j=(n%9)//3
k=(n%3)
元素=d[i][j][k]
对于n=25
,您将得到i=2,j=2,k=1
,这正是您想要的
在python2中,您可以(并且必须)使用普通的
/
操作符,而不是/
,您要做的是将其作为平面或1d数组进行索引。有多种方法可以做到这一点ravel
和重塑(-1)
创建1d视图,flant()
创建1d副本
最有效的是迭代器(一个属性,而不是方法):
(也可以在作业中使用,例如d.flat[25]=0
In [341]: idx = [25, 4, 15]
In [343]: d.flat[idx]
Out[343]: array([25, 4, 15])
要了解3d索引是什么,有一个实用工具,unlavel\u index
(以及相应的ravel\u多索引
)
这是一个元组,一个元素的索引是向下读取的,例如(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
这正是我想要的,因为我想改变原始矩阵。谢谢你使用
平面
迭代器,我认为构建一个单独的视图
没有任何速度优势。平面索引实际上可能比分解的等价物更快。@hpaulj:我认为视图的优势在于它“起作用”例如,您可以计算sum()
覆盖它,或者检查形状
。例如,如果您有一些处理类似数组的对象的方法,这可能会很有用。换句话说,可以将其视为1d数组,就好像它从来都不是3d数组一样。我认为可能是比这更好的解决方案,将此3行线转换为单个属性reference@LouisMaddox:som注释和现在的答案中提到的是,d.flat
不能生成数组的完全平面视图。例如,我们无法计算.sum().flat
的
。如果我们想将平面视图传递给函数,并且该函数需要类似数组的对象,那么这可能会有问题。使用.flat
,它将返回一个flatiter
对象,该对象的工具数量比较有限。np.unravel\u index
进行此计算。flatte()
生成的是一个副本,而不是一个视图。这是一个非常有用的答案,还有一些我不知道的numpy工具。谢谢