Есть ли Pythonic способ транспонировать 1 строку / столбец матрицы numpy?

#python #numpy #matrix #transpose

#python #numpy #матрица #транспонировать

Вопрос:

Представьте, что у меня есть матрица 8×8:
[
0 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1
0 0 0 1 1 1 1 1
0 0 0 0 1 1 1 1
0 0 0 0 0 1 1 1
0 0 0 0 0 0 1 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0
]

Я бы хотел перенести одну строку / столбец из него между 2 точками. Например, если бы я хотел выполнить транспонирование между 2,2 и 6,6 (где 1,1 — крайнее верхнее левое значение), новая матрица должна выглядеть следующим
образом [
0 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1
0 1 0 1 1 0 1 1
0 1 0 0 1 0 1 1
0 1 0 0 0 0 1 1
0 1 1 1 1 0 1 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0
]

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

Спасибо

Комментарии:

1. Разрешена ли библиотека numpy?

2. Да, @Keredu, я использую массивы numpy

3. представьте, что вы можете создать матрицу в вашем примере как x = np.triu(np.ones((8,8), dtype=int), 1)

4. Привет @Scotty1 — проблема не так проста, как выполнение транспонирования матрицы, потому что, как сказано в названии, я бы хотел, чтобы она выполнялась только в одной строке / столбце…

Ответ №1:

Вы могли бы сделать:

 import numpy as np

arr = np.array([
    [0, 1, 1, 1, 1, 1, 1, 1],
    [0, 0, 1, 1, 1, 1, 1, 1],
    [0, 0, 0, 1, 1, 1, 1, 1],
    [0, 0, 0, 0, 1, 1, 1, 1],
    [0, 0, 0, 0, 0, 1, 1, 1],
    [0, 0, 0, 0, 0, 0, 1, 1],
    [0, 0, 0, 0, 0, 0, 0, 1],
    [0, 0, 0, 0, 0, 0, 0, 0]
])

arr[1:6, 1:6] = arr[1:6, 1:6].T
arr[2:5, 2:5] = arr[2:5, 2:5].T

print(arr)
 

Выходной сигнал

 [[0 1 1 1 1 1 1 1]
 [0 0 0 0 0 0 1 1]
 [0 1 0 1 1 0 1 1]
 [0 1 0 0 1 0 1 1]
 [0 1 0 0 0 0 1 1]
 [0 1 1 1 1 0 1 1]
 [0 0 0 0 0 0 0 1]
 [0 0 0 0 0 0 0 0]]
 

Идея состоит в том, чтобы транспонировать подматрицу, а затем еще раз транспонировать внутреннюю часть подматрицы.

Комментарии:

1. звучит расточительно ( O(N^2) операция, когда O(N) она доступна и даже проще для ввода)…

Ответ №2:

Вы можете просто поменять местами столбцы, а затем строки:

 x = np.arange(16).reshape((4, 4))

r0, r1 = 0, 1
c0, c1 = 2, 3

x[:, (c0, c1)] = x[:, (c1, c0)]
x[(r0, r1), :] = x[(r1, r0), :]

x
array([[ 4,  5,  7,  6],
       [ 0,  1,  3,  2],
       [ 8,  9, 11, 10],
       [12, 13, 15, 14]])
 

Специально для вашего примера (и, извините, индексы начинаются с 0, как и предполагала природа):

 # setup
x = np.triu(np.ones((8,8), dtype=int), 1)

p0 = 1, 1
p1 = 5, 5
r0, c0, r1, c1 = p0   p1
 
 # operation
x[:, (c0, c1)] = x[:, (c1, c0)]
x[(r0, r1), :] = x[(r1, r0), :]

print(x)
[[0 1 1 1 1 1 1 1]
 [0 0 0 0 0 0 1 1]
 [0 1 0 1 1 0 1 1]
 [0 1 0 0 1 0 1 1]
 [0 1 0 0 0 0 1 1]
 [0 1 1 1 1 0 1 1]
 [0 0 0 0 0 0 0 1]
 [0 0 0 0 0 0 0 0]]
 

Комментарии:

1. Да, именно так я это и сделал. Мне было интересно, есть ли более красивый, более питонический способ сделать это, но если он наиболее эффективен, то я буду придерживаться его. Спасибо

Ответ №3:

 import numpy as np

matrix = np.array([[1,2,3,4],
                   [5,6,7,8],
                   [9,10,11,12],
                   [13,14,15,16]])

p1 = (1,1)
p2 = (3,3)
sub_matrix = matrix[p1[0]:p2[0], p1[1]:p2[1]]
matrix[p1[0]:p2[0], p1[1]:p2[1]] = np.transpose(sub_matrix)
print(matrix) # returns [[ 1  2  3  4]
              #          [ 5  6 10  8]
              #          [ 9  7 11 12]
              #          [13 14 15 16]]