2016-09-25 3 views
1

Я пытаюсь найти манхэттенское расстояние между всеми парами векторов.Что не так в следующем коде для вычисления расстояния между всеми парами векторов?

import numpy as np 
import itertools 

class vector: 
    def __init__(self): 
     self.a = 0 
     self.b = 0 

c = vector() 
d = vector() 
l = vector() 
m = vector() 

e = [c,d] 
n = [l,m] 
o = np.array(n) 
f = np.array(e) 
p = itertools.product(o,f) 
p = list(p) 
def comp(x): 
    return (x[0].a-x[1].a) + (x[0].b-x[1].b) 

g = np.vectorize(comp) 
print g(p) 

Я получаю ошибку:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/local/lib/python2.7/site-packages/numpy/lib/function_base.py", line 2207, in __call__ 
    return self._vectorize_call(func=func, args=vargs) 
    File "/usr/local/lib/python2.7/site-packages/numpy/lib/function_base.py", line 2270, in _vectorize_call 
    ufunc, otypes = self._get_ufunc_and_otypes(func=func, args=args) 
    File "/usr/local/lib/python2.7/site-packages/numpy/lib/function_base.py", line 2232, in _get_ufunc_and_otypes 
    outputs = func(*inputs) 
    File "<stdin>", line 2, in comp 
AttributeError: vector instance has no attribute '__getitem__' 

ответ

2

я должен сказать, что я бы подойти к этому по-разному. Численный Python не справляется с классами Python и т. Д.

Ваш класс

class vector: 
    def __init__(self): 
     self.a = 0 
     self.b = 0 

Это в основном длина-2 вектор. Так что, если вы собираетесь работать на многих длины-2 векторов, я хотел бы предложить что-то вроде этого:

In [13]: p = np.array([[1, 2], [3, 4], [5, 6]]) 

In [14]: p 
Out[14]: 
array([[1, 2], 
     [3, 4], 
     [5, 6]]) 

Каждой строка представляет собой длину 2 вектора. Существует 3 таких вектора. Это намного намного эффективнее, чем Python list классов Python.

Теперь ваша comp функция

def comp(x): 
    return (x[0].a-x[1].a) + (x[0].b-x[1].b) 

в основном эквивалентна

def comp(x): 
    return (x[0].a+x[0].b) - (x[1].a+x[1].b) 

т.е. компонент суммы первого вектора, за вычетом суммы компонента второго вектора. В таком случае, вы можете эффективно вычислять попарные выходы через

In [15]: q = p.sum(axis=1) 

для вычисления компонент суммы каждого вектора, а затем

In [16]: np.subtract.outer(q, q) 
Out[16]: 
array([[ 0, -4, -8], 
     [ 4, 0, -4], 
     [ 8, 4, 0]]) 
0

так, как вы написали comp, он ожидает, что называемый с двумя кортежами в качестве аргумента, но это не то, что происходит. p - это список кортежей. Когда вы вызываете на нем векторизованную функцию, она преобразуется в массив numpy. Кортежи разбиваются на отдельные столбцы, поэтому вы получаете массив 4x2. Затем ваша функция вызывается в каждой ячейке этого массива. Поэтому он вызывается только одним векторным объектом в качестве аргумента.

Непонятно, что вы пытаетесь выполнить здесь. Если ваши объекты не являются цифрами, вы ничего не выиграете, используя такие вещи, как np.vectorize; вы должны просто вызвать свою функцию в цикле. Если ваши объекты являются числами, просто сохраните их в обычном массиве numpy и используйте лучшие способы вычисления таких расстояний, например, pdist в scipy.