Numpy多维数组中的索引顺序

时间:2014-12-22 16:06:16

标签: python arrays numpy multidimensional-array matplotlib

例如,假设我模拟了一堆粒子随着时间的推移做了某些事情,我有一个名为particles的多维数组,带有这些索引:

  • 粒子的x / y / z坐标(长度为a,对于3d空间为3
  • 单个粒子的索引(长度b
  • (长度c
  • 的时间步长索引

构建数组particles.shape == (a, b, c)particles.shape == (c, b, a)是否更好?

我对约定比对效率更感兴趣:Numpy数组可以设置为C风格(最后一个索引变化最快)或Fortran风格(第一个索引),因此它可以有效地支持任一设置。我也意识到我可以使用transpose以我需要的任何顺序放置索引,但我想尽量减少这些。

我自己开始研究这个问题并找到了对这两种方式的支持:

亲(C,B,A):

  • 默认情况下,Numpy使用C风格的数组,其中最后一个索引变化最快。
  • 大多数向量代数函数(innercross等)都作用于最后一个索引。 (dot作用于最后一个,倒数第二个。)
  • matplotlib集合对象(LineCollectionPolyCollection)期望数组的最后一个轴具有空间坐标。

亲(A,B,C):

  • 如果我使用meshgridmgrid来生成一组点,则会将空间轴放在第一位。例如,np.mgrid[0:5,0:5,0:5].shape == (3,5,5,5)。我意识到这些函数主要用于integer array indexing,但使用它们生成点网格并不罕见。
  • matplotlib scatterplot函数拆分了它们的参数,因此它与数组的形状无关,但ax.plot3d(particles[0], particles[1], particles[2])的类型更短而不是particles[..., 0]
  • 的版本

一般情况下,似乎存在两种不同的约定(可能是由于C和Fortran之间的历史差异),并且不清楚哪些在Numpy社区中更常见,或者更适合我和我#39;正在做。

2 个答案:

答案 0 :(得分:4)

根据我的经验,对于这样的事情的约定与特定文件格式的关系远远超过其他任何事情。但是,有一种快速的方法可以回答哪一种可能最适合您所做的事情:

如果你必须遍历一个轴,你最有可能迭代哪一个?换句话说,最有可能是哪一个:

# a first
for dimension in particles:
    ...

# b first
for particle in particles:
    ...

# c first
for timestep in particles:
    ...

就效率而言,这假定为C顺序,但这实际上与此无关。在python级别,无论内存布局如何,对numpy数组的访问都被视为C-ordered。 (你总是迭代第一个轴,即使它不是内存中最连续的"轴。)

当然,在很多情况下你应该避免在这个问题上直接迭代numpy数组。尽管如此,这是您应该考虑的方式,特别是在磁盘文件结构方面。使您最常见的用例最快/最简单。

如果不出意外,希望这能为您提供一个思考问题的有用方法。

答案 1 :(得分:2)

另一个偏见是,当必须添加新维度时,numpy首选项将在左侧执行。那是x[None,...]是自动的

np.array([x,y,z])   # produces a (3,...) array

np.ones((3,2)) + np.ones((1,2,10)) # error
np.ones((3,2,1)) + np.ones((2,10))  # (3,2,10)

但我不知道这个前置广播如何支持x/y/z坐标的一个位置或另一个位置。

虽然np.dot使用的约定为last/2nd to last,但np.tensordotnp.einsum更加通用。


Apocheir指出在最后一个轴上进行缩减可能需要添加newaxis,例如

 x / np.linalg.norm(x,axis=0)   # automatic newaxis at beginning
 x / np.linalg.norm(x,axis=-1)[...,np.newaxis]  # explicit newaxis

对于小x,此显式newaxis会增加可衡量的执行时间。但对于大x,第二次计算更快。我认为这是因为减去最后一个轴的速度更快 - 那个变化得更快的轴(order='C')。

许多内置缩减方法都有一个keepdims参数,以便在这类用途中进行广播(例如summean)。