In [1019]: a=np.array([[1,2,3],[4,7,5],[9,0,1]])
In [1020]: b=a[:,(0,2)]
这是您正在排序的a
;具有3个字段的结构化数组。它使用相同的数据缓冲区,但将3个整数组解释为字段而不是列。
In [1021]: a.view('i,i,i')
Out[1021]:
array([[(1, 2, 3)],
[(4, 7, 5)],
[(9, 0, 1)]],
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])
通过同样的逻辑,试图view
b
:
In [1022]: b.view('i,i')
/usr/local/bin/ipython3:1: DeprecationWarning: Changing the shape of non-C contiguous array by
descriptor assignment is deprecated. To maintain
the Fortran contiguity of a multidimensional Fortran
array, use 'a.T.view(...).T' instead
#!/usr/bin/python3
....
ValueError: new type not compatible with array.
但是,如果使用3个字段,而不是2,它的工作原理(但具有相同的警告):
In [1023]: b.view('i,i,i')
/usr/local/bin/ipython3:1: DeprecationWarning:...
Out[1023]:
array([[(1, 4, 9), (3, 5, 1)]],
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])
问题是b
是Fortran order
。检查b.flags
或
In [1026]: a.strides
Out[1026]: (12, 4)
In [1027]: b.strides
Out[1027]: (4, 12)
b
是一个副本,而不是一个视图。我不知道,为什么这个建筑b
改变了顺序。
听从警告,我可以这样做:
In [1047]: b.T.view('i,i,i').T
Out[1047]:
array([[(1, 4, 9), (3, 5, 1)]],
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])
默认复制(顺序c)中的b
可被视为2个字段:
In [1042]: b1=b.copy()
In [1043]: b1.strides
Out[1043]: (8, 4)
In [1044]: b1.view('i,i')
Out[1044]:
array([[(1, 3)],
[(4, 5)],
[(9, 1)]],
dtype=[('f0', '<i4'), ('f1', '<i4')])
脚注上:https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
高级索引结果的内存布局针对每个索引操作进行了优化,并且没有特定的内存ory命令可以被假定。
====================
在这种情况下b
用高级索引构成,并且因此是一个拷贝,即使是真正的视图可能不是这样既可见:
In [1052]: a[:,:2].view('i,i')
....
ValueError: new type not compatible with array.
In [1054]: a[:,:2].copy().view('i,i')
Out[1054]:
array([[(1, 2)],
[(4, 7)],
[(9, 0)]],
dtype=[('f0', '<i4'), ('f1', '<i4')])
的观点是选择值的子集: '我,我,X,I,I,X,I,I,X ...',和这不会转化为结构化的dtype。
的a
的结构化视图的作用: '(I,I,I),(I,I,I),...'
可以选择一种结构化阵列的字段的子集:
In [1059]: a1=a.view('i,i,i')
In [1060]: a1
Out[1060]:
array([[(1, 2, 3)],
[(4, 7, 5)],
[(9, 0, 1)]],
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])
In [1061]: b1=a1[['f0','f2']]
In [1062]: b1
Out[1062]:
array([[(1, 3)],
[(4, 5)],
[(9, 1)]],
dtype=[('f0', '<i4'), ('f2', '<i4')])
但是对于这样的视图你可以做什么是有限度的。值可以在a1
中更改,并在a
和b1
中查看。但是如果我尝试更改b1
中的值,则会发生错误。 这是发展的边缘。
我的预感是你会走运。我对这些numpy的内部信息不是很了解,但是在我看来,就像你试图将视角超越可以在不复制数据的情况下所做的那样。 – BrenBarn
@BrenBarn:可能。我只是想看看这里有没有人有任何聪明的黑客。我目前的解决方案只是错误的数据,无法查看,并告诉调用者首先做一个副本......丑陋的,但至少我可以提供一个有用的错误消息。 – Linuxios