Python 从按列排序的方阵中获得较低的对角线索引
我正试图在一条直线的下对角线上创建一个成对的图。因此,我需要平方矩阵下对角线的索引。由于我的绘图顺序,我需要按列对它们进行排序。例如,假设我有以下矩阵4x4:Python 从按列排序的方阵中获得较低的对角线索引,python,numpy,Python,Numpy,我正试图在一条直线的下对角线上创建一个成对的图。因此,我需要平方矩阵下对角线的索引。由于我的绘图顺序,我需要按列对它们进行排序。例如,假设我有以下矩阵4x4: [ 1, 2, 3, 4] [ 5, 6, 8, 7] [ 8, 9, 10, 11] [12, 13, 14, 15] 我需要他们的指数按以下顺序排列:5,8,12,9,13,14。我如何在几行代码中实现这一点?我将分享我的解决方案,但我觉得我可以用一种更优雅的方式来完成 我的解决方案 上下文 我接下来要做的是: >
[ 1, 2, 3, 4]
[ 5, 6, 8, 7]
[ 8, 9, 10, 11]
[12, 13, 14, 15]
我需要他们的指数按以下顺序排列:5,8,12,9,13,14。我如何在几行代码中实现这一点?我将分享我的解决方案,但我觉得我可以用一种更优雅的方式来完成
我的解决方案
上下文
我接下来要做的是:
>>> subplot_idx = a.T[index]
>>> for idx in subplot_idx:
... plt.subplot(n, n, idx)
... # plot something
这个怎么样
n = 4
1 + np.ravel_multi_index(np.triu_indices(n, 1)[::-1], (n, n))
# array([ 5, 9, 13, 10, 14, 15])
与您的解决方案类似,但不需要设置完整的方形阵列。一种更便宜的方法是避免索引创建部分,并使用掩码来创建索引。现在,由于它的行主要顺序是NumPy,并且我们需要较低的diag元素,因此我们需要在输入数组的转置版本上使用较高的diag掩码(将较高的diag元素设置为True的掩码,而其余元素为False)。我们将使用范围数组外部比较有效地创建一个上部诊断掩码,并索引到转置数组中。因此,对于输入数组
a
来说-
r = np.arange(len(a))
out = a.T[r[:,None] < r]
a.T[~np.tri(len(a), dtype=bool)]
同样的想法,使用NumPy内置创建一个较低的diag掩码,从而拥有一个优雅的单行方式(如要求的)-
r = np.arange(len(a))
out = a.T[r[:,None] < r]
a.T[~np.tri(len(a), dtype=bool)]
样本运行-
In [116]: a
Out[116]:
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16]])
In [117]: a.T[~np.tri(len(a), dtype=bool)]
Out[117]: array([ 5, 9, 13, 10, 14, 15])
标杆管理
接近-
# Original soln
def extract_lower_diag_org(a):
n = len(a)
index = np.triu_indices(n, 1)
return a.T[index]
# Proposed soln
def extract_lower_diag_mask(a):
r = np.arange(len(a), dtype=np.uint16)
return a.T[r[:,None] < r]
通过建议的基于掩码的方法,这些大型阵列的速度大大提高。只是澄清一下-索引从0开始,所以你想得到所需的索引-1(4,7,11,8,12,13),对吗?这对我来说似乎足够优雅了。你是在获取索引还是元素本身?@CoffeehouseCoder,我知道这很奇怪,但是的索引是从一开始的:)
In [142]: a = np.random.rand(5000,5000)
In [143]: %timeit extract_lower_diag_org(a)
1 loop, best of 3: 216 ms per loop
In [144]: %timeit extract_lower_diag_mask(a)
10 loops, best of 3: 50.2 ms per loop
In [145]: %timeit a.T[~np.tri(len(a), dtype=bool)]
10 loops, best of 3: 52.1 ms per loop