Python 将numpy数组转换为C-连续顺序的最便宜方法?
下面生成一个C-连续numpy数组:Python 将numpy数组转换为C-连续顺序的最便宜方法?,python,arrays,numpy,Python,Arrays,Numpy,下面生成一个C-连续numpy数组: import numpy a = numpy.ones((1024,1024,5)) 现在,如果我将其切片,结果可能不再相同。例如: bn = a[:, :, n] 从0到4使用n。 我的问题是我需要bn是C-连续的,我需要对a的许多实例这样做。我只需要每个bn一次,并且希望避免这样做 bn = bn.copy(order='C') 我也不想重写我的代码 a = numpy.ones((5,1024,1024)) 有没有比拷贝更快、更便宜的方式获
import numpy
a = numpy.ones((1024,1024,5))
现在,如果我将其切片,结果可能不再相同。例如:
bn = a[:, :, n]
从0到4使用n
。
我的问题是我需要bn
是C-连续的,我需要对a的许多实例这样做。我只需要每个bn
一次,并且希望避免这样做
bn = bn.copy(order='C')
我也不想重写我的代码
a = numpy.ones((5,1024,1024))
有没有比拷贝更快、更便宜的方式获得bn
背景:
我想使用
import hashlib
hashlib.sha1(a[:, :, n]).hexdigest()
不幸的是,这将抛出一个
ValueError
,抱怨订单。因此,如果有另一种快速获取所需哈希值的方法,我也会使用它。要强制numpy数组x
为C-连续,而不在开始时进行不必要的复制,应该使用
x = numpy.asarray(x, order='C')
请注意,如果此数组不是C-连续的,则在效率方面可能与x.copy(order='C')
类似。我认为没有办法解决这个问题。除非将数据复制到新位置,否则无法重新组织内存中数组的对齐方式
重写代码,使其首先使用切片索引,如
numpy.ones((510241024))
似乎是唯一合理的优化方法 这是numpy与C接口时的标准操作。
看看
x=numpy.ascontiguousarray(x)
这是正确的处理方法
如果需要fortran命令,请使用
如前所述,如有必要,该功能将进行复制。所以这是没有办法的。您可以在操作前进行尝试,使短轴成为第一个轴。这将为您提供阵列的视图
In [2]: A=np.random.rand(1024,1024,5)
In [3]: B=np.rollaxis(A,2)
In [4]: B.shape
Out[4]: (5, 1024, 1024)
In [5]: B.flags
Out[5]:
C_CONTIGUOUS : False
F_CONTIGUOUS : False
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
In [6]: A.flags
Out[6]:
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
所以rollaxis也不能解决这个问题。目前的情况是,任何将切片
bn
强制为C连续顺序的尝试都会创建一个副本
如果您不想更改开始使用的形状(并且不需要a
本身的C顺序),一种可能的解决方案是以Fortran顺序从数组a
开始:
>>> a = numpy.ones((1024, 1024, 5), order='f')
然后,切片也是F-连续的:
>>> bn = a[:, :, 0]
>>> bn.flags
C_CONTIGUOUS : False
F_CONTIGUOUS : True
OWNDATA : False
...
这意味着切片bn
的转置将是C顺序,并且转置不会创建副本:
>>> bn.T.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : False
...
然后可以对切片进行散列:
>>> hashlib.sha1(bn.T).hexdigest()
'01dfa447dafe16b9a2972ce05c79410e6a96840e'
另一方面,我只是通过大量调试了解了hashlib的行为,直到我发现异常的真正来源。python文档不应该提到这一点吗?在我看来,这似乎是解决方案的正确路径,但在转换视图时,您正在更改其他两个轴的顺序,这并不好。类似于
a=numpy.ones((5,1024,1024)).transpose(1,2,0)
的东西为您提供了一个既不是C也不是Fortran连续的数组,但当沿着最后一个维度进行索引时,它会生成C连续的切片。我怎么知道“它已经是这样开始的”呢?如果是的话,我就不会犯错误吗?我的案例是使用.values
从pandas中获取一个列。为什么它会或不会是C连续的?例如,您创建了一个2D numpy数组(默认情况下是C顺序的),您将其转置,然后它将是F顺序的。因此,这取决于对阵列执行的操作。使用pandas,块管理器可以在任何情况下使用x.flags
进行检查。