我正在尝试使用this answer中的解决方案按特定列(就地)对numpy数组进行排序。在大多数情况下它可以工作,但它在任何数组上失败,这是另一个数组的视图:
In [35]: columnnum = 2
In [36]: a = np.array([[1,2,3], [4,7,5], [9,0,1]])
In [37]: a
Out[37]:
array([[1, 2, 3],
[4, 7, 5],
[9, 0, 1]])
In [38]: b = a[:,(0, 2)]
In [39]: b
Out[39]:
array([[1, 3],
[4, 5],
[9, 1]])
In [40]: a.view(','.join([a.dtype.str] * a.shape[1])).sort(order=['f%d' % columnnum], axis=0)
In [41]: a
Out[41]:
array([[9, 0, 1],
[1, 2, 3],
[4, 7, 5]])
In [42]: b.view(','.join([b.dtype.str] * b.shape[1])).sort(order=['f%d' % columnnum], axis=0)
ValueError: new type not compatible with array.
看起来numpy不支持视图的视图,这有一定的意义,但我现在无法弄清楚如何获取任何数组所需的视图,无论是它本身是一个观点与否。到目前为止,我还没有找到任何方法来获取有关构建我需要的新视图的必要信息。
目前,我正在使用l = l[l[:,columnnum].argsort()]
就地排序方法,该方法工作正常,但由于我在大型数据集上运行,我想避免额外的内存开销{{ 1}}调用(索引列表)。有没有办法获取有关视图的必要信息或按列进行排序?
答案 0 :(得分:1)
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')])
b
的默认副本(订单c)可以被视为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
高级索引结果的内存布局针对每个索引操作进行了优化,并且不能假定特定的内存顺序。
====================
在这种情况下, 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')])
视图正在选择值的子集:'i,i,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
中的值,则会出错。
这是在发展方面。