Python 从按列排序的方阵中获得较低的对角线索引

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。我如何在几行代码中实现这一点?我将分享我的解决方案,但我觉得我可以用一种更优雅的方式来完成 我的解决方案 上下文 我接下来要做的是: >

我正试图在一条直线的下对角线上创建一个成对的图。因此,我需要平方矩阵下对角线的索引。由于我的绘图顺序,我需要按列对它们进行排序。例如,假设我有以下矩阵4x4:

[ 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