Python 引用numpy arrray而不创建昂贵的副本
假设我有一个函数,要求NumPyPython 引用numpy arrray而不创建昂贵的副本,python,arrays,numpy,reference,slice,Python,Arrays,Numpy,Reference,Slice,假设我有一个函数,要求NumPyndarray具有两个轴,例如,行和列的数据矩阵。如果从这样的数组中分割出一个“列”,那么这个函数也应该工作,因此为了方便起见,它应该执行一些内部X[:,np.newaxis]。但是,我不想为此创建一个新的数组对象,因为在某些情况下这可能会很昂贵 我想知道是否有一个好方法来做这件事。例如,下面的代码是否安全(我的意思是,全局数组是否总是像Pythonlists一样保持不变) 我这样问是因为我听说在某些情况下NumPy数组有时会被复制,但是,我找不到关于这方面的好资
ndarray
具有两个轴,例如,行和列的数据矩阵。如果从这样的数组中分割出一个“列”,那么这个函数也应该工作,因此为了方便起见,它应该执行一些内部X[:,np.newaxis]
。但是,我不想为此创建一个新的数组对象,因为在某些情况下这可能会很昂贵
我想知道是否有一个好方法来做这件事。例如,下面的代码是否安全(我的意思是,全局数组是否总是像Pythonlist
s一样保持不变)
我这样问是因为我听说在某些情况下NumPy数组有时会被复制,但是,我找不到关于这方面的好资源。有什么想法吗 它不应该创建副本。举例说明:
>>> A = np.ones((50000000,))
>>> B = A[:,np.newaxis]
>>> B.flags
C_CONTIGUOUS : False
F_CONTIGUOUS : False
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
请注意OWNDATA:False
-它正在与A共享数据
有关更多详细信息,请查看。基本规则是,除非使用索引数组(例如
a[[1,2,4]]
)或布尔数组(例如a[[True,False,True]]
)进行索引,否则它不会创建副本。几乎所有其他内容都返回一个没有副本的视图。它不应该创建副本-这些类型的操作都只是视图-一个具有更改的数据数组元数据的副本,而不是数据。您可以重新调整输入数组的形状,使其成为M x N
维数组,其中M
是第一个维度的元素数。然后,对其进行切片以获得第一列并对其所有元素求和。不得进行整形和切片
复制
因此,您可以在不使用IF语句的情况下使用这种替代方法-
def some_func2(X):
return X.reshape(X.shape[0],-1)[:,0].sum()
要检查并确认它没有通过整形和切片创建副本,您可以使用np。可以像这样共享内存-
In [515]: X1
Out[515]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
In [516]: np.may_share_memory(X1,X1.reshape(X1.shape[0],-1)[:,0])
Out[516]: True
In [517]: X2
Out[517]: array([1, 4, 7])
In [518]: np.may_share_memory(X2,X2.reshape(X2.shape[0],-1)[:,0])
Out[518]: True
带有np.may\u share\u memory
的True
值很好地表明它们是视图而不是副本。您选择[:,np.newaxis]
的具体原因是什么?如果它是X=X[np.newaxis]
的话,也就是说,当输入是1D数组时,它可以保持形状为2D数组1xn
吗?对不起,我没有提到它,但我想要一个Nx1
维数组。NumPy的美妙之处在于,与列表不同,请勿在切片操作期间复制。你会得到一个轻量级的包装。但这也意味着您可以通过更改片来影响主阵列。我几乎可以肯定,numpy的c代码中分配了一个新的连续内存块(它可能会在返回时被垃圾回收,也可能不会被垃圾回收)。。。它应该很容易用内存分析器进行验证。。。我只知道这一点,因为我只需要和它斗争一两天ago@JoranBeasley至少根据文档“基本切片生成的所有数组始终是原始数组的视图”(基本切片下列出了np.newaxis
)。如果代码做了一些不同的事情,我很乐意被更正!我可以保证,对于一个不能分配30mb连续内存的win32应用程序,我在a=a[:,columns]
上遇到了一个内存错误(正如我所说,它可能会在离开C区后立即被垃圾回收)但这可能不是OP的关注点,可能取决于列是什么——如果是索引列表,我想这是意料之中的。如果这是一个片段,那么它会更令人惊讶。@JoranBeasley如果你能追踪到你案件的细节,这将是一个很好的例子。它通常不需要分配任何内存,因此如果需要,我们应该尝试将其修复。谢谢,我不知道np。可以共享内存
,并且我有一些场景,在这些场景中,这对测试非常有用。我喜欢X.reshape(X.shape[0],-1)
而不是if
+X[:,np.newaxis]
In [515]: X1
Out[515]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
In [516]: np.may_share_memory(X1,X1.reshape(X1.shape[0],-1)[:,0])
Out[516]: True
In [517]: X2
Out[517]: array([1, 4, 7])
In [518]: np.may_share_memory(X2,X2.reshape(X2.shape[0],-1)[:,0])
Out[518]: True