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