有一个2D numpy数组,每行约有500000行,每行512个值:
[
[1,0,1,...,0,0,1], # 512 1's or 0's
[0,1,0,...,0,1,1],
...
[0,0,1,...,1,0,1], # row number 500000
]
如何对行进行排序,就像每行是一个长的512位整数一样?
[
[0,0,1,...,1,0,1],
[0,1,0,...,0,1,1],
[1,0,1,...,0,0,1],
...
]
答案 0 :(得分:3)
您也可以使用void
视图(来自@Jaime here)和argsort
来查看字符串,而不是转换为字符串。
def sort_bin(b):
b_view = np.ascontiguousarray(b).view(np.dtype((np.void, b.dtype.itemsize * b.shape[1])))
return b[np.argsort(b_view.ravel())] #as per Divakar's suggestion
测试
np.random.seed(0)
b = np.random.randint(0, 2, (10,5))
print(b)
print(sort_bin(b))
[[0 1 1 0 1]
[1 1 1 1 1]
[1 0 0 1 0]
...,
[1 0 1 1 0]
[0 1 0 1 1]
[1 1 1 0 1]]
[[0 0 0 0 1]
[0 1 0 1 1]
[0 1 1 0 0]
...,
[1 1 1 0 1]
[1 1 1 1 0]
[1 1 1 1 1]]
由于b_view
只是b
t = np.random.randint(0,2,(2000,512))
%timeit sort_bin(t)
100 loops, best of 3: 3.09 ms per loop
%timeit np.array([[int(i) for i in r] for r in np.sort(np.apply_along_axis(lambda r: ''.join([str(c) for c in r]), 0, t))])
1 loop, best of 3: 3.29 s per loop
实际上快了约1000倍
答案 1 :(得分:0)
你可以用stable方式对它们进行512次排序,从最右边的位开始。
一个较小的例子:假设你想按位对这三个2位数字进行排序:
11
01
00
在第一步中,按正确的位排序,产生:
00
11
01
现在按第一位排序,在这种情况下,我们在该列中有两个0s
。如果您的排序算法不稳定,则允许在结果中以任何顺序放置这些相同的项目,这可能导致01
出现在我们不想要的00
之前,因此我们使用稳定对第一列进行排序,保持相等项的相对顺序,得到所需的:
00
01
11
答案 2 :(得分:0)
A B B1
Dog Cat Car
Dog Cat Pie
Cat Car Pie
Cat Car Cat
Car Pie (null)
Car Cat Car
Car Cat Pie
Cat Pie (null)
的{{1}},然后应用string
因此,如果我们要测试row
:
np.sort()
我们可以使用np.apply_along_axis
创建每个array
的{{1}}:
a = np.array([[1,0,0,0],[0,0,0,0],[1,1,1,1],[0,0,1,1]])
现在会strings
:
row
现在我们可以a = np.apply_along_axis(lambda r: ''.join([str(c) for c in r]), 0, a)
a
与array(['1010', '0010', '0011', '0011'], dtype='<U4')
:
sort
制作strings
:
np.sort()
然后我们可以转换回原始格式:
a = np.sort(a)
使a
:
array(['0010', '0011', '0011', '1010'], dtype='<U4')
如果你想把这一切都塞进一行:
a = np.array([[int(i) for i in r] for r in a])
答案 3 :(得分:0)
这很慢但完成了工作。
def sort_col(arr, col_num=0):
# if we have sorted over all columns return array
if col_num >= arr.shape[1]:
return arr
# sort array over given column
arr_sorted = arr[arr[:, col_num].argsort()]
# if the number of 1s in the given column is not equal to the total number
# of rows neither equal to 0, split on 1 and 0, sort and then merge
if len(arr) > np.sum(arr_sorted[:, col_num]) > 0:
arr_sorted0s = sort_col(arr_sorted[arr_sorted[:, col_num]==0], col_num+1)
arr_sorted1s = sort_col(arr_sorted[arr_sorted[:, col_num]==1], col_num+1)
# change order of stacking if you want ascenting order
return np.vstack((arr_sorted0s, arr_sorted1s))
# if the number of 1s in the given column is equal to the total number
# of rows or equal to 0, just go to the next iteration
return sort_col(arr_sorted, col_num + 1)
np.random.seed(0)
a = np.random.randint(0, 2, (5, 4))
print(a)
print(sort_col(a))
# prints
[[0 1 1 0]
[1 1 1 1]
[1 1 1 0]
[0 1 0 0]
[0 0 0 1]]
[[0 0 0 1]
[0 1 0 0]
[0 1 1 0]
[1 1 1 0]
[1 1 1 1]]
编辑。或者更好地使用Daniels解决方案。在我发布代码之前,我没有检查新的答案。