Closed NicolasPce closed 2 years ago
Hola Nico 🙋🏻♀️! Seguimos con más proyectos, y ahora es el turno del proyecto de las geoqueries!
Con el readme Nico, vamos a aceptar pulpo como animal de compañia, pero hay que darle una vueltita más a este readme 😔. Te dejo por aquí unos detalles por si te aportan valor de cara al futuro:
Pones las librerías con sus links a la documentación oficial que has usado lo cual esta super bien. Solo como detalle, si te fijas lo tienes todo en una línea lo que hace que sea menos intuitivo de leer. Mejor si lo ponemos como una lista.
Dices que usas la BBDD de companies, pero que tiene esa base de datos. Lo ideal, describirla brevemente.
Explicar un poco como es la empresa que te ha contratado, para saber porque te basas en ciertos criterios.
En este proyecto hemos realizado muchos pasos, llamadas a la API para sacar información, almacenamiento en mongo, geoqueries, etc. En este caso, podemos incluir una especie de workflow del proyecto.
En tu caso no tienes muchas carpetas, pero en caso de que las tuvieras, recuerda que un pequeño resumen de la estructura del repo, que carpetas tenemos y uqe ficheros nos podemos encontrar.
¿Qué API has usado para extraer información?
¿Dónde has almacenado la información?
¿Cómo has calculado las distancias? ¿Qué criterios has usado?
Vamos con la organización del repo que en este caso solo tienes dos ficheros pero podriamos haber añadido más para que el repo estuviera más organizado.
¿Qué es lo que podríamos hacer?
Separar cada uno de los pasos del proyecto en distintos jupyters. Es decir:
Al tener varios jupyters, podemos crearnos una carpeta de Notebooks
con ellos numerados para saber cual es el orden de trabajo.
Nuestra carpeta de src
con nuestras funciones. En este proyecto tenemos que crear muchas funciones para evitar repetir código una y otro vez.
Una carpeta de data
donde guardemos los datos que nos bajado de la API. Cuando trabajamos con APIs y tenemos todos nuestros datos, lo ideal es que guardemos esos datos. ¿por qué? Imagina que la API deja de funcionar, que agotas el número de llamadas y que no tienes los datos que ya sacaste guardados. Nos quedaríamos sin datos!! HORROR 😱!!! Si por lo menos tenemos una parte o todos guardados podremos seguir adelante con el trabajo.
Tienes algunos imports
en mitad del jupyter. Recuerda, por convenio los imports deben ir al inicio del jupyter, para que cuando empecemos a leer tu código sepamos que librerías vamos a usar a lo largo del proyecto.
Tienes tres funciones, latt
, long
y typePoint
separadas. En este caso, dado que el objetivo de las tres es el mismo yo las juntaría todas en una.
Podrías hacer algo así:
# como el objetivo principal de estas funciones es crear el type point, en este caso podemos hacer una única llamando a las coumnas que no interesan.
def type_point (df_col):
return {'type': 'Point', 'coordinates': [df_col['location']['lng'], df_col['location']['lat']}
# 🚨 Y recuerda que las funciones deben estar en el src
Nicooooo, los prints infinitos plisss 🙏.
Haces las llamadas a la API para cada ciudad y requerimiento de forma independiente. Pero si te fijas estas repartiendo el código una y otra vez. Cuando esto pasa es señal de... HACER FUNCIONES!
Te dejo por aquí algunas ideas de pseudo-código por si te aporta valor:
def get_data(LAT, LONG, radio):
clave = os.getenv(("token"))
url = f"https://maps.googleapis.com/maps/api/place/nearbysearch/json?location={LAT},{LONG}&radius={radio}&keyword={SC}&key={clave}"
payload={}
headers = {}
response = requests.request("GET", url, headers=headers, data=payload)
data = response.json()['results']
return pd.DataFrame(data)
# de la misma forma que hacemos esto aquí, podemos crearnos otra función de limpieza del dataframe que devolvemos en el ejercicio anterior.
def clean_api(df, category):
df['latitude'] = df.geometry.apply(latt)
df['longitude'] = df.geometry.apply(long)
df["points"] = df.apply(lambda x: typePoint(x['latitude'], x['longitude']), axis = 1)
df.drop(["geometry"] , axis=1, inplace=True)
df.insert(0, 'type', category)
return df
El import request
lo tienes cargado de forma recurrente a lo largo del jupyter.
Por si te aporta valor en el futuro, en mongo tenemos un método que se llama GeoNear
que nos permite hacer una query de geolocalización que nos va a devolver la distancia en km de cada una de nuestras ciudades a los datos que tenemos en la BBDD.
Te dejo por aqui un video que lo explica super bien!
De la misma que repites código para sacar la info de la base de datos, lo haces con los mapas. De nuevo, una funcioncita nos ayudaría mucho.
Otra cosa que he visto es que no tienes código para meter los datos de la API limpios en mongo a través de python. Esto también lo podemos hacer, con el método de mongo insert_many
. Esto nos va a permitir automatizar nuestros procesos.
¿Cómo lo podríamos hacer?
def queries_close (gdf, nombre):
# donde :
# nombre es el nombre que le quieras dar a la coleccion
# gdf el dataframe con tus datos.
client = MongoClient()
db = client.TUBASEDEDATOS
collection = db.create_collection(name = f"{nombre}")
collection = db[f"{nombre}"]
collection.create_index([("loc", "2dsphere")]) #creamos el indice de 2d sphere
data = gdf.to_dict(orient='records') # para meter el dataframe en mongo necesitamos que sea un diccionario. Por lo que lo cambiamos.
collection.insert_many(data)
Bueno Nico, la verdad es que no ha sido tu mejor obra. Aún así tienes código muy interesante. Te dejo por aquí unos cuantos tips sobre la corrección:
.py
Venga Nico! En general buen trabajo, has conseguido alcanzar los objetivos del proyecto, usar una API, meter los datos en una BBDD y hacer geoqueries 👏🏽!
Venga que ya no queda nada 🔥🔥🔥!!
https://github.com/NicolasPce/P3