Преобразование списка, содержащего элементы ниже диагонали матрицы, в полную матрицу

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

И это будет желаемый результат:

введите здесь описание изображения

До этого момента я пытался заставить это работать с обычным синтаксисом в python, реализовав следующий код:

list_similarities = [1,0.1,0.6,0.4,1,0.1,0.2,1,0.7,1]

the_range = range(0,4)

list_of_lists = []
counter_element = 0
counter = -1
for element in the_range:
    counter += 1
    counter_element += len(the_range)-element
    intermediary = (len(the_range)-element)
    first_element = counter_element-intermediary
    line_list = list_similarities[first_element:counter_element]
    # counter = 0, then no need to add an additional element
    # print(line_list)
    if counter == 0:
        "do nothing"
    elif counter >0:
        for item in range(0,element):
            from_list_to_add = list_of_lists[item]
            element_to_add = from_list_to_add[item+1]
            line_list.insert(0,element_to_add)
    print(line_list)
    list_of_lists.append(line_list.copy())
    # print("final lists:", list_of_lists)


# print(counter_element)
print("final lists:", list_of_lists)

Однако вывод следующий:

финальные списки: [[1, 0.1, 0.6, 0.4], [0.1, 1, 0.1, 0.2], [0.1, 0.1, 1, 0.7], [0.7, 0.1, 0.1, 1]]

Он делает первые 2 списка, которые представляют 2 строки из матрицы, но не будет делать последние 2 из-за того, как работает мой код, и пока я не знаю решения для этого.

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

Спасибо за ваше время и предложения!

ОБНОВЛЕНИЕ: Мой вопрос не является дубликатом Numpy: преобразовать массив в треугольную матрицу, потому что я не хочу создавать матрицу, в которой мои значения из массива являются частью только нижней треугольной матрицы, а также находятся в верхней треугольной матрице.


person Adrian    schedule 19.11.2018    source источник
comment
Возможный дубликат Numpy: преобразовать массив в треугольную матрицу   -  person Matthieu Brucher    schedule 19.11.2018
comment
@ Андриан, посмотри мой ответ и дай мне знать, если это поможет   -  person seralouk    schedule 19.11.2018
comment
@seralouk спасибо, что нашли время найти решение! Он работает так, как ожидалось :)   -  person Adrian    schedule 19.11.2018


Ответы (2)


Решение с использованием numpy.triu_indices и numpy.tril_indices. Я руководил каждым шагом с комментариями. Суть в том, чтобы сначала найти верхние правые индексы, присвоить значение из списка, а затем сделать матрицу симметричной.

import numpy as np

n = 4
l = [1,0.1,0.6,0.4,1,0.1,0.2,1,0.7,1]

a = np.zeros((n,n)) # Initialize nxn matrix
triu = np.triu_indices(n) # Find upper right indices of a triangular nxn matrix
tril = np.tril_indices(n, -1) # Find lower left indices of a triangular nxn matrix
a[triu] = l # Assign list values to upper right matrix
a[tril] = a.T[tril] # Make the matrix symmetric

print(a)

Вывод

[[1.  0.1 0.6 0.4]
 [0.1 1.  0.1 0.2]
 [0.6 0.1 1.  0.7]
 [0.4 0.2 0.7 1. ]]
person b-fg    schedule 19.11.2018
comment
я отправил немного другой и более короткий ответ - person seralouk; 19.11.2018
comment
@ Адриан, я упростил свой ответ, который тоже работает и чище. - person b-fg; 19.11.2018

Это очень просто, используя numpy.triu_indices_from.

Используйте это:

import numpy as np

list_similarities = [1,0.1,0.6,0.4,1,0.1,0.2,1,0.7,1]
n = 4

Full_matrix = np.zeros((n,n))
inds = np.triu_indices_from(Full_matrix, k = 0)
# use [:] to copy the list and avoid any problem if the initial list is further needed
Full_matrix[inds] = list_similarities[:]
Full_matrix[(inds[1], inds[0])] = list_similarities[:]

Результаты

array([[1. , 0.1, 0.6, 0.4],
       [0.1, 1. , 0.1, 0.2],
       [0.6, 0.1, 1. , 0.7],
       [0.4, 0.2, 0.7, 1. ]])

P.S. Подробнее о том, почему я копирую список, используя list_similarities[:] здесь

person seralouk    schedule 19.11.2018
comment
Я создаю копию списка. и это лучший способ сделать это. Между list_similarities = list_similarities[:] и list_similarities = list_similarities огромная разница. Это самый безопасный способ - person seralouk; 19.11.2018