J'ai travaillé sur un projet extrêmement sensible au temps (qui doit malheureusement être en python) et l'une des fonctions largement utilisées est une fonction qui calcule le centroïde d'une liste de (x, y) tuples. Pour illustrer:
def centroid(*points):
x_coords = [p[0] for p in points]
y_coords = [p[1] for p in points]
_len = len(points)
centroid_x = sum(x_coords)/_len
centroid_y = sum(y_coords)/_len
return [centroid_x, centroid_y]
où
>>> centroid((0, 0), (10, 0), (10, 10), (0, 10))
[5, 5]
Cette fonction est assez rapide. L’exemple ci-dessus s’achève en moyenne en 1,49e-05 secondes sur mon système, mais je cherche le moyen le plus rapide de calculer le centroïde. Avez-vous des idées?
Une de mes solutions consistait à effectuer les opérations suivantes (où l
est la liste des n-uplets):
map(len(l).__rtruediv__, map(sum, Zip(*l)))
Ce qui se situe entre 1.01e-05 et 9.6e-06 secondes, mais se convertit malheureusement en une liste (en entourant toute la déclaration dans list( ... )
) presque double temps de calcul.
EDIT: Les suggestions sont les bienvenues en python pur MAIS PAS numpy.
EDIT2: Je viens de découvrir que si une variable distincte est conservée pour la longueur de la liste de tuples, l’implémentation ci-dessus avec map
fonctionne de manière fiable sous 9.2e-06 secondes, mais le problème de la conversion en liste est toujours présent.
EDIT3:
Maintenant, je n'accepte que des réponses en python pur, PAS en numpy (désolé pour ceux qui ont déjà répondu en numpy!)
import numpy as np
data = np.random.randint(0, 10, size=(100000, 2))
c'est rapide
def centeroidnp(arr):
length = arr.shape[0]
sum_x = np.sum(arr[:, 0])
sum_y = np.sum(arr[:, 1])
return sum_x/length, sum_y/length
%timeit centeroidnp(data)
10000 loops, best of 3: 181 µs per loop
étonnamment, c'est beaucoup plus lent:
%timeit data.mean(axis=0)
1000 loops, best of 3: 1.75 ms per loop
numpy me semble très rapide ...
Pour être complet:
def centeroidpython(data):
x, y = Zip(*data)
l = len(x)
return sum(x) / l, sum(y) / l
#take the data conversion out to be fair!
data = list(Tuple(i) for i in data)
%timeit centeroidpython(data)
10 loops, best of 3: 57 ms per loop
Ceci est une implémentation naïve de Numpy, je ne peux pas le chronométrer ici alors je me demande comment cela fonctionne:
import numpy as np
arr = np.asarray(points)
length = arr.shape[0]
sum_x = np.sum(arr[:, 0])
sum_y = np.sum(arr[:, 1])
return sum_x / length, sum_y / length
Vous transmettez les points à centroid()
sous forme de paramètres distincts, qui sont ensuite placés dans un seul Tuple avec *points
. Il serait plus rapide de simplement passer une liste ou un itérateur avec des points.