Caso práctico con Matplotlib y Geopandas

0
2440

Pandas, Matplotlib y Geopandas

1. Introducción

Cuando decides comprar o alquilar una vivienda es importante tener conocimiento sobre qué rango de valores pueden rondar el inmueble. Esto es importante ya que te permite reducir el riesgo de inversión o incluso maximizar la rentabilizad a la hora de invertir.

El objetivo de este artículo es resolver el problema que hizo Juan Antonio en este tutorial pero esta vez cambiando la tecnología, en nuestro caso lo haremos con Python. De esta forma, ampliamos el abanico de posibilidades a la hora de resolver un problema.

2. Entender los datasets

Para realizar el análisis, vamos a hacer uso de dos datasets públicos que nos ofrece Idealista. El primero de ellos, será el dataset con la información de las paradas de metro de Madrid y el segundo, será el dataset que nos dice el precio por m2 de compra y alquiler a 500m de dichas paradas de metro

Comenzamos con el análisis del primer conjunto de datos para conocer que es cada campo. En primer lugar, importamos las librerías necesarias para leer un json a través del protocolo http.

import pandas as pd
import json
import requests
def read_from_url(url):
    uri = str(url).replace(' ', '%20')
    response = requests.get(uri)
    content = response.content.decode('utf-8')
    return json.loads(content)
data = read_from_url('https://idealista.carto.com:443/api/v2/sql?q=select * from public.paradas_metro_madrid')
paradas_metro = pd.DataFrame(data['rows'])
display(paradas_metro.sample(5))

Echando un ojo al dataframe, vemos que de las paradas de metro nos interesan sólo algunos campos:

  • cartodb_id: es un índice númerico propio de la BBDD.
  • the_geom y the_geom_webmercator son campos propios de un estándar GIS llamado GeoJSON.
  • place: es el lugar que ocupa la estación en la línea.
  • id: identificador único de todas las estaciones.
  • name: nombre de la parada de metro.
  • line: línea de metro.
  • lat y lng: son coordenadas terrestres (latitud y longitud).

De estos campos, nos vamos a quedar sólo con id, name, line, place, lat y lng

Vamos a realizar la misma operación, pero ahora para el otro dataset.

data = read_from_url('https://idealista.carto.com:443/api/v2/sql?q=select * from public.precio_metro_201605')
precio_metro = pd.DataFrame(data['rows'])
display(precio_metro.sample(5))

Analizando el dataframe, podemos observar las siguientes columnas.

  • cartodb_id: es un índice numérico propio de la BBDD.
  • the_geom y the_geom_webmercator son campos propios de un estándar GIS llamado GeoJSON como en el caso anterior.
  • date: fecha de registro.
  • id: identificador único de la estaciones.
  • name: nombre de la parada de metro.
  • sale: precio del metro cuadrado para una venta.
  • rental: precio del metro cuadrado de un alquiler.

De este dataframe, solo nos vamos a quedar con id, sale, rental.

Sabiendo los datos que queremos de cada dataframe, vamos a proceder a hacer un merge de ambos de las columnas que nos interesan.

# Limpiamos dataframe primero
paradas_metro = paradas_metro.loc[:, ['id', 'name', 'line', 'place', 'lat', 'lng']]
precio_metro = precio_metro.loc[:,['id', 'sale', 'rental']]

# realizamos un merge de ambos frames
paradas_metro_precio = paradas_metro.merge(precio_metro, how="inner")
display(paradas_metro_precio.sample(5))

3. Toma de decisiones

Hasta este punto, tenemos un dataframe relleno de datos pero sin saber muy bien qué hacer con ellos. Vamos a proponer una serie de preguntas y responderlas para los distintos casos que puedan aparecer.

    1. Soy un inversor y quiero obtener una gráfica del rendimiento de los inmuebles.
    1. Tengo dinero ahorrado y quiero saber qué beneficio obtengo por cada euro invertido.
    1. Me gustaría cambiar de casa y quiero saber los precios y cuántos inmuebles hay en cada linea de metro.

Antes tenemos que importar la librería de matplotlib para poder graficar los datos.

import matplotlib.pyplot as plt
# 1
def performance():
    paradas_metro_precio['performance'] = (paradas_metro_precio['rental'] * 12) / paradas_metro_precio['sale']
    return paradas_metro_precio.sort_values(by='performance', ascending=False)

df_performance = performance()
h = df_performance.plot(x='line', y='performance', kind='scatter')
plt.show()

png

Como podemos observar, la L1 es la que genera mayor rendimiento pero depende de la parada que elijas, ya que tiene algunas que cuyo rendimiento es del 4%. La L11 puede ser una mejor alternativa para invertir ya que toda la línea tiene un rendimiento entre el 7% y el 9% aproximadamente.

Para hallar el rendimiento que hay en cada parada de metro, hemos planteado la siguiente ecuación: performance = 12months * rental / sale · 100

# 2
def benefit(amount):
    df_aux = df_performance
    df_aux[f'benefit{int(amount/1000)}k'] = round(df_aux['performance'] * amount, 2)
    return df_aux.sort_values(by=f'benefit{int(amount/1000)}k', ascending=False)

amount = 10000
df_benefit = benefit(amount)
h = df_benefit[df_benefit['line'] == 'L11'].plot(x='name', y=f'benefit{int(amount/1000)}k')
plt.xticks(rotation=15)
plt.show()

png

Como en la pregunta anterior hemos visto que la L11 puede ser una de las mejores alternativas para invertir, hemos calculado el beneficio que hay en cada parada de esas líneas. Por tanto, como vemos en la gráfica, la mejor parada donde buscar un inmueble sería Abrantes, ya que genera más del 9%, y la peor sería La Fortuna, porque solo obtienes algo menos del 7% por cada euro invertido.

Para saber el beneficio que hemos obtenido hemos realizado la siguiente ecuación: benefit = performance · amount

Para la pregunta 3, vamos a hacer uso de Geopandas que nos permite posicionar correctamente los datos de nuestro conjunto a través de una nueva columna, que se generará a continuación, cuyos valores son en formato GeoJSON.

# 3
import geopandas as gpd
import os
path = os.path.join('res', '20cc5389-1e0a-4d3b-8804-742ae1c71587202034-1-1j5kf1k.9aj3.shp')

# Cargar datos
locs_metro = gpd.read_file(path, encoding='utf-8')

print(locs_metro)
# Limpiar datos
locs_metro = locs_metro[locs_metro['CORONATARI'] == 'A'].loc[:, ['DENOMINACI', 'geometry']]
locs_metro['name'] = locs_metro['DENOMINACI'].str.lower()
df_benefit['name'] = df_benefit['name'].str.lower()
del locs_metro['DENOMINACI']

#Merge y verificar que el dataframe resultante es correcto
mrg = locs_metro.merge(df_benefit, on='name')
display(mrg.sample(4))
geometry name id line place lat lng sale rental performance benefit10k
27 POINT (442994.523 4476738.133) cartagena 172 L7 17 40.439336 -3.672158 3462.437488 14.086485 0.048820 488.20
22 POINT (440135.509 4474628.991) callao 112 L5 17 40.420082 -3.705667 3749.744169 15.280450 0.048901 489.01
113 POINT (441283.025 4477555.927) nuevos ministerios 186 L8 1 40.446550 -3.692418 4072.123003 14.040057 0.041374 413.74
34 POINT (440361.306 4477979.100) alvarado 8 L1 8 40.450331 -3.703318 3110.129023 13.620316 0.052552 525.52
# Dibujar
fig,ax = plt.subplots(3,1,figsize=(10,20), sharex=True, sharey=True)

mrg.plot(
    column='sale', cmap='coolwarm', 
    ax=ax[0], legend=True, 
    legend_kwds={'label': 'Distribución del precio de venta en las lineas de metro', 'orientation': "horizontal"})
mrg.plot(
    column='rental', cmap='coolwarm',
    ax=ax[1], legend=True, 
    legend_kwds={'label': 'Distribución del precio de alquiler en las lineas de metro', 'orientation': "horizontal"})
mrg.plot(
    column='performance', cmap='coolwarm',
    ax=ax[2], legend=True, 
    legend_kwds={'label': 'Distribución del rendimiento de los inmuebles en las lineas de metro', 'orientation': "horizontal"})

plt.xticks([])
plt.yticks([])
plt.show()

png

En los 3 plots mostrados arriba tenemos información de la distribución de los precios de venta y alquiler por metro cuadrado y también el rendimiento que tienen los inmuebles que están a 500 metros de cada parada de metro. Con dichas imágenes, somos capaces de tener una visión económica en función de la parada de metro, que nos ayudará a tomar mejores decisiones en función de nuestras necesidades.

4. Conclusiones

Hemos visto otra manera de poder resolver problemas relacionados con el campo de DataScience. Siendo Python y R los lenguajes estrella en este ámbito, es bueno poder compararlos para ver las ventajas y desventajas que pueda haber entre ellos.

Con este artículo hemos aprendido a realizar las siguientes operaciones:

  • Leer un dataset desde una api.
  • Analizar el conjunto de datos antes de proceder a su manipulación.
  • Realizar un merge de dos dataframes y con los campos que nosotros queremos tratar.
  • Añadir nuevas columnas a nuestro conjunto de datos.
  • Graficar por medio de Matplotlib para sacar conclusiones.
  • Formatear las gráficas para conseguir una mejor presentación de los datos.
  • Usar Geopandas para las columnas que tienen latitud y longitud.

Enlaces y referencias

Daniel Álvarez Gil
Ingeniero de Software apasionado por la excelencia y el aprendizaje constante. Especializado en arquitecturas escalables, patrones de diseño y despliegue continuo. Transformo desafíos en soluciones de alto impacto que agregan valor tangible. Creo en la ingeniería sólida y la cobertura exhaustiva de código para lograr estabilidad y rendimiento óptimo. Listo para impulsar proyectos hacia el éxito con innovación y calidad. ¡Conectemos para abordar los desafíos tecnológicos juntos! ??

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad