Question

J'essaie de regrouper en utilisant DBSCAN (implémentation de scikit learn) et les données de localisation.Mes données sont au format tableau np, mais pour utiliser DBSCAN avec la formule Haversine, je dois créer une matrice de distance.J'obtiens l'erreur suivante lorsque j'essaie de faire cela (une erreur « module » non appelable.) D'après ce que j'ai lu en ligne, il s'agit d'une erreur d'importation, mais je suis presque sûr que ce n'est pas le cas pour moi.J'ai créé ma propre formule de distance haversine, mais je suis sûr que l'erreur ne vient pas de cela.

Ce sont mes données d'entrée, un tableau np (ResultArray).

[[ 53.3252628   -6.2644198 ]
[ 53.3287395   -6.2646543 ]
[ 53.33321202  -6.24785807]
[ 53.3261015   -6.2598324 ]
[ 53.325291    -6.2644105 ]
[ 53.3281323   -6.2661467 ]
[ 53.3253074   -6.2644483 ]
[ 53.3388147   -6.2338417 ]
[ 53.3381102   -6.2343826 ]
[ 53.3253074   -6.2644483 ]
[ 53.3228188   -6.2625379 ]
[ 53.3253074   -6.2644483 ]]

Et c'est la ligne de code qui contient des erreurs.

distance_matrix = sp.spatial.distance.squareform(sp.spatial.distance.pdist
(ResultArray,(lambda u,v: haversine(u,v))))

Voici le message d'erreur :

File "Location.py", line 48, in <module>
distance_matrix = sp.spatial.distance.squareform(sp.spatial.distance.pdist
(ResArray,(lambda u,v: haversine(u,v))))
File "/usr/lib/python2.7/dist-packages/scipy/spatial/distance.py", line 1118, in pdist
dm[k] = dfun(X[i], X[j])
File "Location.py", line 48, in <lambda>
distance_matrix = sp.spatial.distance.squareform(sp.spatial.distance.pdist
(ResArray,(lambda u,v: haversine(u,v))))
TypeError: 'module' object is not callable

J'importe scipy en tant que sp.(importer scipy en tant que sp)

Était-ce utile?

La solution

Veuillez vous référer à la réponse @TommasoF.Cette réponse est fausse : pdist permet de choisir une fonction de distance personnalisée.Je supprimerai la réponse une fois qu'elle ne sera plus choisie comme bonne réponse.

Simplement scipyc'est pdist ne permet pas de passer dans une fonction de distance personnalisée.Comme on peut le lire dans le documents, vous disposez de quelques options, mais la distance côté haverside ne figure pas dans la liste des métriques prises en charge.

(Matlab pdist prend cependant en charge l'option, voir ici)

vous devez faire le calcul "manuellement", c'est-à-direavec des boucles, quelque chose comme ceci fonctionnera :

from numpy import array,zeros

def haversine(lon1, lat1, lon2, lat2):
    """  See the link below for a possible implementation """
    pass

#example input (your's, truncated)
ResultArray = array([[ 53.3252628, -6.2644198 ],
                     [ 53.3287395  , -6.2646543 ],
                     [ 53.33321202 , -6.24785807],
                     [ 53.3253074  , -6.2644483 ]])

N = ResultArray.shape[0]
distance_matrix = zeros((N, N))
for i in xrange(N):
    for j in xrange(N):
        lati, loni = ResultArray[i]
        latj, lonj = ResultArray[j]
        distance_matrix[i, j] = haversine(loni, lati, lonj, latj)
        distance_matrix[j, i] = distance_matrix[i, j]

print distance_matrix
[[ 0.          0.38666203  1.41010971  0.00530489]
 [ 0.38666203  0.          1.22043364  0.38163748]
 [ 1.41010971  1.22043364  0.          1.40848782]
 [ 0.00530489  0.38163748  1.40848782  0.        ]]

Juste pour référence, une implémentation en Python de Haverside peut être trouvée ici.

Autres conseils

Avec SciPY, vous pouvez définir une fonction de distance personnalisée comme suggérée par la documentation de ce Link et rapporté ici pour plus de commodité:

Y = pdist(X, f)
Computes the distance between all pairs of vectors in X using the user supplied 2-arity function f. For example, Euclidean distance between the vectors could be computed as follows:

dm = pdist(X, lambda u, v: np.sqrt(((u-v)**2).sum()))

Ici, je signale ma version du code inspiré sur le code de ce Lien :

from numpy import sin,cos,arctan2,sqrt,pi # import from numpy
# earth's mean radius = 6,371km
EARTHRADIUS = 6371.0

def getDistanceByHaversine(loc1, loc2):
    '''Haversine formula - give coordinates as a 2D numpy array of
    (lat_denter link description hereecimal,lon_decimal) pairs'''
    #      
    # "unpack" our numpy array, this extracts column wise arrays
    lat1 = loc1[1]
    lon1 = loc1[0]
    lat2 = loc2[1]
    lon2 = loc2[0]
    #
    # convert to radians ##### Completely identical
    lon1 = lon1 * pi / 180.0
    lon2 = lon2 * pi / 180.0
    lat1 = lat1 * pi / 180.0
    lat2 = lat2 * pi / 180.0
    #
    # haversine formula #### Same, but atan2 named arctan2 in numpy
    dlon = lon2 - lon1
    dlat = lat2 - lat1
    a = (sin(dlat/2))**2 + cos(lat1) * cos(lat2) * (sin(dlon/2.0))**2
    c = 2.0 * arctan2(sqrt(a), sqrt(1.0-a))
    km = EARTHRADIUS * c
    return km

et appelant de la manière suivante:

D = spatial.distance.pdist(A, lambda u, v: getDistanceByHaversine(u,v))

Dans ma mise en œuvre, la matrice A a comme une première colonne les valeurs de longitude et la deuxième colonne les valeurs de latitude exprimées en degrés décimaux.

Vous pouvez désormais regrouper des données spatiales de latitude et de longitude avec la métrique DBSCAN et haversine de scikit-learn sans précalculer une matrice de distance à l'aide de scipy.

db = DBSCAN(eps=2/6371., min_samples=5, algorithm='ball_tree', metric='haversine').fit(np.radians(coordinates))

Cela vient de ce tutoriel sur regrouper des données spatiales avec scikit-learn DBSCAN.Notons en particulier que le eps la valeur est de 2 km divisé par 6371 (rayon terrestre en km) pour la convertir en radians.Notez également que .fit() prend les coordonnées en unités radians pour la métrique haversine.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top