Python 对两个预先排序的numpy数组执行argsort
我有几组数组。在每个组中,所有数组都是一维的,都具有相同的长度。每个组中有一个主数组,该数组已排序 例如:Python 对两个预先排序的numpy数组执行argsort,python,numpy,Python,Numpy,我有几组数组。在每个组中,所有数组都是一维的,都具有相同的长度。每个组中有一个主数组,该数组已排序 例如: grp_1 = [ np.array([10, 20, 30, 40]), np.array(["A", "C", "E", "G"]), ] grp_2 = [ np.array([15, 25, 35]), np.array(["Z", "Y", "X"]), ] def combine_groups(groups): com
grp_1 = [
np.array([10, 20, 30, 40]),
np.array(["A", "C", "E", "G"]),
]
grp_2 = [
np.array([15, 25, 35]),
np.array(["Z", "Y", "X"]),
]
def combine_groups(groups):
combined_arrays = [np.concatenate([grp[idx] for grp in groups]) for idx in range(len(groups[0]))]
sort_indices = np.argsort(combined_arrays[0], kind="mergesort")
# Merge sort rather than quicksort because the former is stable
return [arr[sort_indices] for arr in combined_arrays]
现在我想合并组中相应的元素。我希望这样做能够使结果的主数组得到排序(以稳定的方式)。例如:
grp_1 = [
np.array([10, 20, 30, 40]),
np.array(["A", "C", "E", "G"]),
]
grp_2 = [
np.array([15, 25, 35]),
np.array(["Z", "Y", "X"]),
]
def combine_groups(groups):
combined_arrays = [np.concatenate([grp[idx] for grp in groups]) for idx in range(len(groups[0]))]
sort_indices = np.argsort(combined_arrays[0], kind="mergesort")
# Merge sort rather than quicksort because the former is stable
return [arr[sort_indices] for arr in combined_arrays]
这是可行的,而且很好,但是(对于比本例大得多的阵列),它比需要的慢得多。合并排序是O(N log(N)),而合并已经排序的数组应该是O(N)事务
我遇到了cytoolz
软件包,它有一个merge\u排序的
软件包,在对我的主阵列进行排序时,它会将numpy从水中吹出来。不幸的是,我需要得到结果索引,这样我也可以转换非主数组
因此:上述方法是否比使用numpy的argsort
更快?tl;博士
只需像现在这样使用合并排序。之前的问题和类似的问题都表明,如果不自己编写一些cython代码(甚至可能不这样),就无法击败已经使用的方法
没有合并排序的方法
只需压缩分组,然后使用cytoolz.merge\u sorted
:
from cytoolz import merge_sorted
# it will be an iterator that yields (10, 'A'), (15, 'Z'), (20, 'C'), (25, 'Y'), (30, 'E'), (35, 'X'), (40, 'G')
it = merge_sorted(zip(*grp_1), zip(*grp_2))
# unzip the tuples back into your desired arrays
grp_comb = [np.array(d) for d in zip(*it)]
print(grp_comb)
ix = grp_1[0].searchsorted(grp_2[0])
grp_comb= [np.insert(grp_1[i], ix, grp_2[i]) for i in range(2)]
print(grp_comb)
输出:
[array([10, 15, 20, 25, 30, 35, 40]), array(['A', 'Z', 'C', 'Y', 'E', 'X', 'G'], dtype='<U1')]
[array([10, 15, 20, 25, 30, 35, 40]), array(['A', 'Z', 'C', 'Y', 'E', 'X', 'G'], dtype='<U1')]
输出:
[array([10, 15, 20, 25, 30, 35, 40]), array(['A', 'Z', 'C', 'Y', 'E', 'X', 'G'], dtype='<U1')]
[array([10, 15, 20, 25, 30, 35, 40]), array(['A', 'Z', 'C', 'Y', 'E', 'X', 'G'], dtype='<U1')]
以下是时间安排:
%%timeit
combine_groups(grp_1, grp_2)
6.84 µs ± 154 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit
combine_groups_ms(grp_1, grp_2)
10.4 µs ± 249 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit
combine_groups_ssi(grp_1, grp_2)
36.3 µs ± 1.27 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
因此,您最初尝试使用concatenate后跟merge sort实际上比我编写的直接利用预排序的代码要快。类似的问题也一直存在,并产生了类似的基准。查看的详细信息,我认为这可能是因为合并两个排序列表离合并排序的最佳性能场景只有一步之遥