NumPy индексы k-й диагонали

Я хотел бы выполнить арифметику с k-й диагональю numpy.array. Мне нужны эти индексы. Например, что-то вроде:

>>> a = numpy.eye(2)
>>> a[numpy.diag_indices(a, k=-1)] = 5
>>> a
array([[ 1.,  0.],
       [ 5.,  1.]])

К сожалению, diag_indices возвращает только индексы, составляющие главную диагональ, поэтому на данный момент я делаю:

a += numpy.diag([5], -1)

Но это не кажется таким красивым или надежным. :-)

Есть ли способ в numpy получить индексы, отличные от главной диагонали?


person K3---rnc    schedule 07.06.2012    source источник


Ответы (6)


Итак, поскольку np.diag_indices() не имеет той же функциональности, что и np.triu_indices() для получения k-х диагоналей/треугольников, другой подход состоит в том, чтобы просто использовать np.eye(n,k) для построения матрицы nxn с единицами. на k-й диагонали, а затем используйте np.where, чтобы извлечь кортеж индексов, где расположены единицы.

Итак, мы можем сделать это, просто:

T = np.where(np.eye(5,k=-1) == 1)

Это дополнительное выделение матрицы глаза, которое в некоторых случаях может быть чрезмерным, но это легко сделать одной строкой.

person user49404    schedule 03.01.2021
comment
Хотя теоретически это может дать ответ на вопрос, было бы лучше, если бы вы добавили текст, объясняющий, почему ваш ответ после того, как автор вопроса уже принял его 8 лет назад, должен быть хорошим вариантом для каждого читателя. - person Steve; 03.01.2021
comment
Спасибо за предложение, готово. - person user49404; 03.01.2021

Немного поздновато, но эта версия работает и для k = 0 (и не переделывает массивы, поэтому копировать не нужно).

def kth_diag_indices(a, k):
    rows, cols = np.diag_indices_from(a)
    if k < 0:
        return rows[-k:], cols[:k]
    elif k > 0:
        return rows[:-k], cols[k:]
    else:
        return rows, cols
person Hans Then    schedule 06.08.2013

Вот способ:

  1. Создайте массивы значений индекса.
  2. Получите нужные значения диагонального индекса.
  3. Вот и все! :)

Как это:

>>> import numpy as np
>>> rows, cols = np.indices((3,3))
>>> row_vals = np.diag(rows, k=-1)
>>> col_vals = np.diag(cols, k=-1)
>>> z = np.zeros((3,3))
>>> z[row_vals, col_vals]=1
>>> z
array([[ 0.,  0.,  0.],
       [ 1.,  0.,  0.],
       [ 0.,  1.,  0.]])
person fraxel    schedule 07.06.2012

Индексы k-й диагонали a можно вычислить с помощью

def kth_diag_indices(a, k):
    rowidx, colidx = np.diag_indices_from(a)
    colidx = colidx.copy()  # rowidx and colidx share the same buffer

    if k > 0:
        colidx += k
    else:
        rowidx -= k
    k = np.abs(k)

    return rowidx[:-k], colidx[:-k]

Демо:

>>> a
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])
>>> a[kth_diag_indices(a, 1)]
array([ 1,  7, 13, 19])
>>> a[kth_diag_indices(a, 2)]
array([ 2,  8, 14])
>>> a[kth_diag_indices(a, -1)]
array([ 5, 11, 17, 23])
person Fred Foo    schedule 07.06.2012

Есть другое решение. Создайте матрицу E с помощью np.eye. Вы можете просто изменить главную диагональ, как показано ниже. Затем создайте еще две матрицы с параметром k в глазу. В конце просто сложите все матрицы вместе.

E = np.eye(5)
E = E*2
F = -1*np.eye(len(E),k=1)
G = -1*np.eye(len(E),k=-1)

E = E+F+G
print(E)
person Jonas Apelt    schedule 11.05.2020

Используйте 1_

Где k задает расположение по диагонали от центра.

т.е. {k=0: центр по умолчанию, k=(-1): 1 ряд слева от центра, k=1: 1 ряд справа от центра}

Затем выполните арифметические действия, как обычно.

Ознакомьтесь с документацией здесь: np.diag().

Примеры:

In [3]: np.diag(np.arange(6), k=0)
Out[3]: 
array([[0, 0, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0],
       [0, 0, 2, 0, 0, 0],
       [0, 0, 0, 3, 0, 0],
       [0, 0, 0, 0, 4, 0],
       [0, 0, 0, 0, 0, 5]])

In [4]: np.diag(np.arange(6), k=1)
Out[4]: 
array([[0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 2, 0, 0, 0],
       [0, 0, 0, 0, 3, 0, 0],
       [0, 0, 0, 0, 0, 4, 0],
       [0, 0, 0, 0, 0, 0, 5],
       [0, 0, 0, 0, 0, 0, 0]])

In [5]: np.diag(np.arange(6), k=-1)
Out[5]: 
array([[0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0, 0],
       [0, 0, 2, 0, 0, 0, 0],
       [0, 0, 0, 3, 0, 0, 0],
       [0, 0, 0, 0, 4, 0, 0],
       [0, 0, 0, 0, 0, 5, 0]])
person agconti    schedule 06.08.2013
comment
да, я знаю, как построить новую диагональную матрицу. Но описанный выше метод не совсем применим, когда мне нужно изменить существующую матрицу. - person K3---rnc; 07.08.2013
comment
Почему бы и нет? Создайте матрицу с единицами на k-й диагонали и используйте ее для индексации исходной матрицы. - person Stefan; 19.01.2017
comment
@Stefan Это не работает для неквадратных массивов. Пожалуйста, используйте другие ответы. - person Corey Levinson; 15.02.2020