在不创建昂贵副本的情况下引用numpy arrray

时间:2015-05-12 20:09:03

标签: python arrays numpy reference slice

假设我有一个函数要求NumPy ndarray有2个轴,例如行和列的数据矩阵。如果从这样的数组中切出“列”,则此函数也应该起作用,因此为方便起见,它应该执行一些内部X[:, np.newaxis]。但是,我不想为此创建一个新的数组对象,因为在某些情况下这可能很昂贵。

我想知道是否有一个好方法。例如,以下代码是否安全(我的意思是,全局数组总是是否会像Python list那样保持不变)?

X1 = np.array([[1,2,3], [4,5,6], [7,8,9]])
X2 = np.array([1,4,7])

def some_func(X):
    if len(X.shape) == 1:
        X = X[:, np.newaxis]
    return X[:,0].sum()       

some_func(X2)
some_func(X1[:, 0])
some_func(X1)

我在问,因为我听说在某些情况下有时会复制NumPy数组,但是,我找不到一个关于此的好资源。有任何想法吗?

3 个答案:

答案 0 :(得分:5)

它不应该创建副本。例如:

>>> 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共享数据。

有关详细信息,请查看http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html。基本规则是,除非您使用索引数组(例如A[[1,2,4]])或布尔数组(例如A[[True, False, True]])进行索引,否则它不会创建副本。几乎所有其他东西都返回一个没有副本的视图。

答案 1 :(得分:1)

它不应该创建副本 - 这些类型的操作都只是视图 - 具有更改的ndarray元数据的副本,而不是数据。

答案 2 :(得分:0)

您可以重塑输入数组以强制它为M x N维数组,其中M是第一维的元素数。然后,将其切片以获得第一列并对其所有元素求和。不得重塑和切片 制作副本。

所以,你可以在没有IF语句的情况下采用这种替代方法 -

def some_func2(X):
    return X.reshape(X.shape[0],-1)[:,0].sum()

要检查并确认它没有使用整形和切片创建副本,您可以像{ - 1>}那样使用np.may_share_memory -

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

带有True的{​​{1}}值是指标,它们是视图而非​​副本。