#python #arrays #numpy
#python #массивы #numpy
Вопрос:
Здравствуйте, в настоящее время я пытаюсь преобразовать этот массив
test=np.array([[0,0],[0,1],[1,1],[3,0]])
и использование расстояния Манхэттена для преобразования этого массива в эту форму
[0., 1., 2., 3.]
[1., 0., 1., 4.]
[2., 1., 0., 3.,
[3., 4., 3., 0.]
код выглядит следующим образом
list_x=[]
newarray=np.array([])
length=len(test)
for i in range(length):
for j in range(length):
print('i=',i)
print('j=',j)
var=sum(abs(a-b) for a,b in zip(test[i],test[j]))
list_x.append(var)
newarray= np.append(newarray,list_x,axis = 0)
list_x=[]
но результат кода продолжает давать мне это:
array([0., 1., 2., 3., 1., 0., 1., 4., 2., 1., 0., 3., 3., 4., 3., 0.])
есть ли проблема в моем np.append(), которая мешает преобразовать его в массив 4 * 4 shap?
Ответ №1:
Вы могли бы использовать scikit-learn manhattan_distances
для получения всех попарных расстояний Манхэттена, упростив вышесказанное до одного вызова функции:
from sklearn.metrics.pairwise import manhattan_distances
manhattan_distances(test)
array([[0., 1., 2., 3.],
[1., 0., 1., 4.],
[2., 1., 0., 3.],
[3., 4., 3., 0.]])
Если вы хотите получить расстояние с помощью цикла for, я бы посоветовал вам вместо этого использовать списки python. Чтобы в итоге получить вложенный список, сгенерируйте внутренний список с расстояниями строки до остальных и добавляйте его во внешний список на каждой итерации:
out=[]
for i in range(length):
new_row = []
for j in range(length):
var=sum(abs(a-b) for a,b in zip(test[i],test[j]))
new_row.append(var)
out.append(new_row)
print(out)
# [[0, 1, 2, 3], [1, 0, 1, 4], [2, 1, 0, 3], [3, 4, 3, 0]]
Комментарии:
1. или используйте свой оригинал… z = np.array([0., 1., 2., 3., 1., 0., 1., 4., 2., 1., 0., 3., 3., 4., 3., 0.]) и z.изменить форму (4,4)
Ответ №2:
Другой способ сделать это — использовать Scipy:
from scipy.spatial.distance import cdist
cdist(test,test,'cityblock')
вывод:
[[0. 1. 2. 3.]
[1. 0. 1. 4.]
[2. 1. 0. 3.]
[3. 4. 3. 0.]]
Сравнение:
#@ehsan's solution
def m1(test):
return cdist(test,test,'cityblock')
#@yatu's solution
def m2(test):
return manhattan_distances(test)
in_ = [np.random.randint(0,10,(n,2)) for n in [10,100,1000,10000]]
Для больших массивов они, похоже, имеют аналогичную производительность, но для меньшего массива (около 1000 строк) m1 кажется быстрее.
Комментарии:
1. Я знаю функцию cdist, но цель этой задачи — вручную выровнять расстояние до Манхэттена, и у меня проблема только в функции добавления
2. @RAbeeq Тогда я неправильно понял проблему. Обязательно ли использовать циклы? вы все еще можете реализовать это с помощью numpy без циклов. Цикл массива вообще не рекомендуется и выполняется медленно. Если вам нужны циклы, я думаю, что ответ Яту охватывает это. Если вам не нужно использовать циклы, я могу помочь реализовать это с помощью массивов.
3. нет необходимости, но благодарю вас за помощь, я действительно благодарю вас