2015-08-22 36 views
1

我试图将2D ndarray视图作为记录或结构化阵列进行复制。这似乎很好地工作,如果a拥有它的数据获取ndarray的重新阵列视图(也可以是视图)

>>> a = np.array([[ 1, 391, 14, 26], 
       [ 17, 371, 15, 30], 
       [641, 340, 4, 7]]) 
>>> b = a.view(zip('abcd',[a.dtype]*4)) 
array([[(1, 391, 14, 26)], 
     [(17, 371, 15, 30)], 
     [(641, 340, 4, 7)]], 
     dtype=[('a', '<i8'), ('b', '<i8'), ('c', '<i8'), ('d', '<i8')]) 
>>> b.base is a 
True 

但如果a已经是一个视图,这个失败。这里有一个例子

>>> b = a[:,[0,2,1,3]] 
>>> b.base is None 
False 
>>> b.view(zip('abcd',[a.dtype]*4)) 
ValueError: new type not compatible with array. 

有趣的是,在这种情况下b.base是视图

>>> (b.base == b.T).all() 
True 

的转置因此它是有道理的numpy的无法创建的那个我想要的视图。

但是,如果我用

>>> b = np.take(a,[0,2,1,3],axis=1) 

这导致b是数据的正确副本,以便采取recarray观点的作品。侧面问题:有人可以解释这种行为与花式索引相反吗?

我的问题是,我这样做是错误的吗?正在考虑我不支持的方式吗?如果是这样,那么正确的做法是什么?

回答

1

(大编辑)

bF_CONTINGUOUS(见b.flags)。在视场的数目,然后需要匹配的b行数,而不是列的数目:

In [204]: b=a[:,[0,2,1,3]].view('i4,i4,i4') 
In [205]: b 
Out[205]: 
array([[(0, 4, 8), (2, 6, 10), (1, 5, 9), (3, 7, 11)]], 
     dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')]) 

一个更简单的情况下是a.copy(order='F').view('i4,i4,i4')

np.take(a,[0,2,1,3],axis=1)a[:,[0,2,1,3]].copy()产生C_CONTIGUOUS副本,并且因此可以用4个字段查看。

还请注意b.base有3列。


(解决这个问题前面绊)

做一个观点是不是一个问题。

a = np.arange(12).reshape(3,4) 
a.view('i4,i4,i4,i4') 

没有问题。

使第一b的副本也可以工作:

b=a[:,[0,2,1,3]].copy() 
b.view('i4,i4,i4,i4') 

首届b(无复印件)是F_CONTIGUOUS(看b.flags)。这就是您的b.base == b.T显示的内容。

np.take产生与bcopy相同种类的阵列 - 即相同的标志和相同的__array_interface__显示。

a[[0,2,1],:].view('i4,i4,i4,i4') 
a.T[[0,2,1,3],:].T.view('i4,i4,i4,i4') 

如果我换成纯数组索引的混合切片和数组索引:

a[[[0],[1],[2]],[0,2,1,3]].view('i4,i4,i4,i4') 

结果是C_CONTIGUOUS

是工作以外的事情。因此,我还没有解释[:, [...]]中的详细信息 - 具体说明为什么它会生成F_CONTIGUOUS副本。

混合基本/高级索引文档部分确实警告存储器布局可以改变:

http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#combining-advanced-and-basic-indexing

在最简单的情况下,仅存在单一的先进索引。例如,单个高级索引可以替换切片,并且结果数组将是相同的,但是,它是一个副本并且可能具有不同的内存布局。如果可能,切片是优选的。

+0

谢谢!我不知道内存布局可能会这样改变。清楚的是,我知道索引像'a [:,[0,2,1,3]'会返回一个副本,但我不知道它可能是'F_CONTIGOUS'或'np.take'会总是返回一个'C_CONTIGUOUS'(这个numpy文档说''np.take'与花式索引做同样的事情,这在这个例子中似乎是错误的)。你会如何处理这种特殊的观点(没有复制),并且始终有效?检查数组是否为'F \ C_CONTIGOUS'是不好的做法吗? – toes