Страницы

Поиск по вопросам

суббота, 4 января 2020 г.

Действия с элементами матрицы и ее диагональю

#python #массивы #циклы #матрицы #numpy


Добрый день! 

Вопрос: есть некий лист с элементами, например 

      X = [0.1, 0.7 , 1, 1.35]


Нужно  создать  массив, где в каждой строке элемент по порядку добавляется ко всем
остальным, причем чтобы сам этот элемент не учитывался ( первый добавляем ко второму,третьему...;
второй к первому,третьему,... и т.д. . Если просто запустить цикл (использую numpy):

   import numpy as np

   X = map(np.array,[X])
   X = [0.1, 0.5 , 1, 1.5]
   X = ( X[:,None] + X[:] )

 #Результат
 [[ 0.2   0.8   1.1   1.45]
  [ 0.8   1.4   1.7   2.05]
  [ 1.1   1.7   2.    2.35]
  [ 1.45  2.05  2.35  2.7 ]]


но диагональные элементы нужно исключить, то есть результат должен быть:

   [[  0.8   1.1   1.45]
    [ 0.8    1.7   2.05]
    [ 1.1    1.7    2.35]
    [ 1.45   2.05   2.35 ]]


Подскажите, как реализовать такое? И еще как потом найти сумму каждой строки?

А если нужно прибавить другой лист, такого же размера (например 

Y = [0.3, 0.5, 0.7, 0.9]

     (X[:,None] + X[:]) + (Y[:,None] + Y[:]) 


или 

      X[:,None] + Y[:]


как изменить код в таком случае? 
    


Ответы

Ответ 1



Я не уверен что до конца вас понял. Вот мое решение: def f(array): new = [x+y for x in array for y in array if y!=x] return new print(f([1, 2, 3])) Результат: [3, 4, 3, 5, 4, 5] Делал без numpy. Но переделать будет не сложно. UPDATE: def for_stack(array): list_for_num_array = [] for i in array: list_for_num_array.append([x+y for x in i for y in i if y!= x]) return np.array(list_for_num_array) X = np.array([[0.1, 0.7 , 1, 1.35]]) print(for_stack(X[:None])) Результат: [[ 0.8, 1.1, 1.45, 0.8, 1.7, 2.05, 1.1, 1.7, 2.35, 1.45, 2.05, 2.35]] Можно еще так: foo = lambda array: ([j+n for i in array for x, j in enumerate(i) for y, n in enumerate(i) if x != y]) Вариант с индексами: def for_stack(array): list_for_num_array = [] for i in array: list_for_num_array.append([j+n for x, j in enumerate(i) for y, n in enumerate(i) if x != y]) return np.array(list_for_num_array) X = np.array([[1, 2, 2], [1, 2, 2]]) print(for_stack(X[:None])) Результат: [[3 3 3 4 3 4], [3 3 3 4 3 4]] Еще один UPDATE: def for_stack(array): list_for_num_array = [] try: for i, j in enumerate(array): list_for_num_array.append([x+n for x, n in zip(array[i], array[i+1])]) except IndexError: pass return np.array(list_for_num_array) X = np.array([[0.1, 0.7 , 1, 1.35], [2, 3, 4, 5]]) print(for_stack(X[:None])) Результат: [[ 2.1 3.7 5. 6.35]] Складываем каждый X[n] + Y[n]. UPD #3 Автор задавал вопрос как удалить диагональ матрицы: arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) foo = lambda array: np.delete(array, np.diagonal(array-1)) Результат: [[2 3 4 6 7 8]]

Ответ 2



Можно сделать так: In [221]: X = np.array([0.1, 0.7 , 1, 1.35]) In [222]: l = len(X) In [223]: A = np.delete(X[:,None] + X[:], np.arange(0, l**2, l+1)).reshape(l,l-1) In [224]: A Out[224]: array([[ 0.8 , 1.1 , 1.45], [ 0.8 , 1.7 , 2.05], [ 1.1 , 1.7 , 2.35], [ 1.45, 2.05, 2.35]]) найти сумму каждой строки: In [225]: A.sum(axis=1) Out[225]: array([ 3.35, 4.55, 5.15, 5.85]) Некоторые пояснения: np.delete() удаляет элементы матрицы по указанным индексам. Причем по умолчанию np.delete() сначала преобразует матрицу в одномерный (flattened) массив и соответственно ожидает индексы для такого 1D массива: Например удаление второго элемента диагонали по индексу (1,1) (со значением 1.4) - для "flattened" матрицы этот элемент имеет индекс 5: In [228]: np.delete(X[:,None] + X[:], 5) Out[228]: array([ 0.2 , 0.8 , 1.1 , 1.45, 0.8 , 1.7 , 2.05, 1.1 , 1.7 , 2. , 2.35, 1.45, 2.05, 2.35, 2.7 ]) np.arange(0, l**2, l+1) - вернет нам индексы диагональных элементов в одномерном "flattened" массиве (для квадратной матрицы): In [229]: np.arange(0, l**2, l+1) Out[229]: array([ 0, 5, 10, 15]) получится: In [230]: np.delete(X[:,None] + X[:], np.arange(0, l**2, l+1)) Out[230]: array([ 0.8 , 1.1 , 1.45, 0.8 , 1.7 , 2.05, 1.1 , 1.7 , 2.35, 1.45, 2.05, 2.35]) дальше преобразуем к нужной 2D матрице: In [231]: np.delete(X[:,None] + X[:], np.arange(0, l**2, l+1)).reshape(l,l-1) Out[231]: array([[ 0.8 , 1.1 , 1.45], [ 0.8 , 1.7 , 2.05], [ 1.1 , 1.7 , 2.35], [ 1.45, 2.05, 2.35]])

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

Отправить комментарий