Pandas, Matplotlib y Geopandas
- 1. Introducción
- 2. Entender los datasets
- 3. Toma de decisiones
- 4. Conclusiones
- Enlaces y referencias
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.
-
- Soy un inversor y quiero obtener una gráfica del rendimiento de los inmuebles.
- Tengo dinero ahorrado y quiero saber qué beneficio obtengo por cada euro invertido.
- 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()
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()
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()
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.