Добрый день!
Вопрос: есть некий лист с элементами, например
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]])