Numpy多维数组中索引的顺序

Apo*_*eir 5 python arrays numpy matplotlib multidimensional-array

例如,假设我正在模拟一堆随时间变化的粒子,并且有一个particles使用这些索引调用的多维数组:

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

构造这样的数组更好particles.shape == (a, b, c)还是particles.shape == (c, b, a)

我对约定更感兴趣而不是效率:Numpy数组可以以C样式(最后一个索引变化最快)或Fortran样式(第一个索引)设置,因此它可以有效地支持这两种设置。我也意识到我可以用来transpose按我需要的任何顺序放置索引,但是我想将其最小化。

我本人开始对此进行研究,并找到了对这两种方式的支持:

Pro-(c,b,a):

  • 默认情况下,Numpy使用C样式的数组,其中最后一个索引是变化最快的。
  • 大多数的向量代数函数(innercross等)作用于最后一个索引。(dot作用于一个的最后一个和另一个的倒数第二个。)
  • 所述matplotlib收集对象(LineCollectionPolyCollection)期待与过去轴的空间坐标的阵列。

Pro-(a,b,c):

  • 如果我要使用meshgridmgrid产生一组点,它将把空间轴放在第一位。例如,np.mgrid[0:5,0:5,0:5].shape == (3,5,5,5)。我意识到这些函数主要用于整数数组索引,但是使用它们生成点网格并不少见。
  • matplotlib scatterplot功能分裂出它们的参数,所以它的不可知的阵列的形状,但ax.plot3d(particles[0], particles[1], particles[2])短于与版本键入particles[..., 0]

通常,似乎存在两种不同的约定(可能是由于C和Fortran之间的历史差异),目前尚不清楚Numpy社区中哪个更常见,或更适合我在做什么。

Joe*_*ton 4

根据我的经验,此类约定与特定文件格式的关系比其他任何东西都大。但是,有一种快速方法可以回答哪一个最适合您正在做的事情:

如果必须迭代一个轴,您最有可能迭代哪一个轴? 换句话说,以下哪一个最有可能:

# a first
for dimension in particles:
    ...

# b first
for particle in particles:
    ...

# c first
for timestep in particles:
    ...
Run Code Online (Sandbox Code Playgroud)

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

当然,在很多情况下,您应该避免直接迭代 numpy 数组。尽管如此,这就是您应该考虑的方式,特别是当涉及到磁盘上的文件结构时。让您最常见的用例成为最快/最简单的。

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