#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]])
Комментариев нет:
Отправить комментарий