Me gustaría saber cuál es la mejor solución para obtener las distancias desde la API de Google Maps distancia para mi trama de datos compuesta de coordenadas (origen y destino) que está a unos 75 k filas.
#Origin #Destination
1 (40.7127837, -74.0059413) (34.0522342, -118.2436849)
2 (41.8781136, -87.6297982) (29.7604267, -95.3698028)
3 (39.9525839, -75.1652215) (40.7127837, -74.0059413)
4 (41.8781136, -87.6297982) (34.0522342, -118.2436849)
5 (29.7604267, -95.3698028) (39.9525839, -75.1652215)
Hasta ahora mi código itera a través de la trama de datos y llamadas a la API de copiar el valor de la distancia en la columna de la nueva "distancia".
df['distance'] = ""
for index, row in df.iterrows():
result = gmaps.distance_matrix(row['origin'], row['destination'], mode='driving')
status = result['rows'][0]['elements'][0]['status']
if status == "OK": # Handle "no result" exception
KM = int(result['rows'][0]['elements'][0]['distance']['value'] / 1000)
df['distance'].iloc[index] = KM
else:
df['distance'].iloc[index] = 0
df.to_csv('distance.csv')
Me sale el resultado deseado, pero por lo que he leído a través de la iteración trama de datos es bastante ineficiente y debe ser evitado. Tardó 20 secondes por 240 filas, por lo que se necesitaría para hacer todo 1h30 trama de datos. Tenga en cuenta que una vez hecho, no hay necesidad de volver a correr más, sólo las nuevas pocas nuevas filas al mes (~ 500).
Lo que haría que la mejor solución a este problema?
Editar: si alguien tiene experiencia con la API de Google distancia y sus limitaciones ningún tips / mejores prácticas es bienvenida.
Traté de entender acerca de cualquier limitación sobre llamadas simultáneas aquí , pero no pude encontrar nada. algunas sugerencias
Evitar bucles
Sobre su código prefiero saltarme los bucles y el uso aplico primero
def get_gmaps_distance(row):
result = gmaps.distance_matrix(row['origin'], row['destination'], mode='driving')
status = result['rows'][0]['elements'][0]['status']
if status == "OK":
KM = int(result['rows'][0]['elements'][0]['distance']['value'] / 1000)
else:
KM = 0
return KM
df["distance"] = df.apply(get_gmaps_distance, axis=1)
Dividir la trama de datos y el uso de multiprocesamiento
import multiprocessing as mp
def parallelize(fun, vec, cores=mp.cpu_count()):
with mp.Pool(cores) as p:
res = p.map(fun, vec)
return res
# split your dataframe in many chunks as the number of cores
df = np.array_split(df, mp.cpu_count())
# this use your functions for every chunck
def parallel_distance(x):
x["distance"] = x.apply(get_gmaps_distance, axis=1)
return x
df = parallelize(parallel_distance, df)
df = pd.concat(df, ignore_index=True, sort=False)
No calcule dos veces a la misma distancia (excepto $$$)
En caso de que haya duplicados fila que debe caer algunas de ellas
grp = df.drop_duplicates(["origin", "destination"]).reset_index(drop=True)
Aquí no lo hice de sobreescritura df
, ya que posiblemente contienen más información que necesita y se puede combinar los resultados de la misma.
grp["distance"] = grp.apply(get_gmaps_distance, axis=1)
df = pd.merge(df, grp, how="left")
Reducir decimales
Usted debe hacer esta pregunta: ¿realmente necesito para ser exacta al séptimo decimal? Como 1 grado de latitud es ~ 111 kilometros al séptimo decimal le da una precisión de hasta ~ 1 cm. Se entiende la idea de esta cuando-menos es más , donde la reducción de decimales que mejoraron el modelo.
Conclusión
Si, finalmente, puede utilizar todos los métodos sugeridos que usted podría conseguir algunas mejoras interesantes. Me gustaría que los comentas aquí, ya que no tengo una clave de API personal a tratar por mí mismo.