El objetivo de este trabajo es comprobar si se está utilizando la plataforma Airbnb por parte de empresas, en lugar de particulares, para alquiler turístico en el centro de Madrid.
Datos abiertos de Inside Airbnb: Fichero alojamientos Madrid detallado
In [46]:
from urllib import request
from urllib.error import URLError
# Leemos el fichero desde la url.
try:
f = request.urlopen('http://aprendeconalf.es/python/trabajos/datos/madrid-airbnb-listings-small.csv')
# El fichero no existe
except URLError:
print('¡La url no existe!')
else:
# Creamos una lista con las líneas del fichero.
lineas = f.read().decode('utf-8').splitlines()
# Extraemos los nombres de las columnas de la primera fila partiendo la cadena por el carácter de tabulación.
columnas = lineas[0].split('\t')
seleccion = ['id', 'host_id', 'neighbourhood_group_cleansed', 'accommodates', 'price']
# Creamos un diccionario para traducir el nombre de las columnas
traduccion = {'id':'id', 'host_id':'anfitrion', 'neighbourhood_group_cleansed':'distrito', 'accommodates':'plazas', 'price':'precio'}
# Creamos la lista de alojamientos
alojamientos = []
# Recorremos las lineas del fichero desde la 1 hasta el final
for linea in lineas[1:]:
# Creamos el diccionario que contendrá la información del alojamiento.
alojamiento = {}
# Creamos una lista con los campo partiendo la línea por el carácter de tabulación.
campos = linea.split('\t')
# Recorremos los campos de la línea
for i in range(len(columnas)):
# Para cada campo añadimos al diccionario el par con clave el nombre de la columna y valor el campo de la posición i.
if columnas[i] in seleccion:
alojamiento[traduccion[columnas[i]]] = campos[i]
# Añadimos el diccionario a la lista de alojamientos.
alojamientos.append(alojamiento)
print(alojamientos)
In [47]:
def alojamientos_distritos(alojamientos):
'''
Función que devuelve un diccionario con el número de alojamientos en cada distrito.
Parámetros:
- alojamientos: Es una lista de diccionarios, donde cada diccionario contiene los datos de un alojamiento.
Devuelve: Un diccionario con el número de alojamientos por distrito.
'''
# Creamos el diccionario
alojamiento_distritos = {}
# Recorremos la lista de alojamientos
for alojamiento in alojamientos:
# Si el distrito ya aparece como clave del diccionario, incrementamos su valor en uno
if alojamiento['distrito'] in alojamiento_distritos.keys():
alojamiento_distritos[alojamiento['distrito']] += 1
# Si el distrito no aparece como clave del diccionario, lo añadimos con valor 1.
else:
alojamiento_distritos[alojamiento['distrito']] = 1
return alojamiento_distritos
# Ejemplo
print(alojamientos_distritos(alojamientos))
In [48]:
def filtrar_plazas(alojamientos, plazas):
'''
Función que devuelve una lista con los alojamientos que tienen un número de plazas mayor o igual que uno dado.
Parámetros:
- alojamientos: Es una lista de diccionarios, donde cada diccionario contiene los datos de un alojamiento.
Devuelve: Un diccionario con el número de alojamientos por distrito.
- plazas: Es un entero con el número mínimo de plazas.
Devuelve: Una lista con los alojamientos que tienen un número de plazas mayor o igual que plazas.
'''
return [alojamiento for alojamiento in alojamientos if int(alojamiento['plazas']) >= plazas]
# Ejemplo
filtro = filtrar_plazas(alojamientos, 10)
print(filtro)
In [49]:
def alojamientos_baratos(alojamientos, distrito, n):
'''
Función que devuelve una lista con los n alojamientos más baratos en un distrito dado.
Parámetros:
- alojamientos: Es una lista de diccionarios, donde cada diccionario contiene los datos de un alojamiento.
Devuelve: Un diccionario con el número de alojamientos por distrito.
- distrito: Es una cadena con el nombre del distrito.
- n: Es un entero con el número de alojamientos a devolver.
Devuelve: Una lista con los n alojamientos más baratos del distrito dado.
'''
# Filtramos los alojamientos del distrito
alojamientos_distrito = [alojamiento for alojamiento in alojamientos if alojamiento['distrito'] == distrito]
# Definimos una función de ordenación con la clave para la ordenación
def orden(dict): return float(dict['precio'][1:])
# Ordenamos la lista de alojamientos con la función de ordenación
ranking_alojamientos = sorted(alojamientos_distrito, key = orden)
return ranking_alojamientos[:n]
# Ejemplo
top_arganzuela = alojamientos_baratos(alojamientos, 'Arganzuela', 10)
print(top_arganzuela)
In [50]:
def alojamientos_anfitriones(alojamientos):
'''
Función que devuelve un diccionario con el número de alojamientos de cada anfitrión.
Parámetros:
- alojamientos: Es una lista de diccionarios, donde cada diccionario contiene los datos de un alojamiento.
Devuelve: Un diccionario con el número de alojamientos por anfitrión.
'''
# Creamos el diccionario
alojamiento_anfitriones = {}
# Recorremos la lista de alojamientos
for alojamiento in alojamientos:
# Si el anfitrión ya aparece como clave del diccionario, incrementamos su valor en uno
if alojamiento['anfitrion'] in alojamiento_anfitriones.keys():
alojamiento_anfitriones[alojamiento['anfitrion']] += 1
# Si el anfitrión no aparece como clave del diccionario, lo añadimos con valor 1.
else:
alojamiento_anfitriones[alojamiento['anfitrion']] = 1
return alojamiento_anfitriones
# Ejemplo
anfitriones = alojamientos_anfitriones(alojamientos)
print(anfitriones)
In [51]:
import pandas as pd
# Creamos un DataFrame desde la url del fichero csv
try:
alojamientos = pd.read_csv('../datos/madrid-airbnb-listings-small.csv', sep = '\t')
except URLError:
print('La url no existe')
else:
# Renombramos los nombres de las columnas que queremos
alojamientos.rename(columns = {'host_id': 'anfitrion', 'listing_url': 'url', 'room_type':'tipo_alojamiento', 'neighbourhood_group_cleansed':'distrito', 'price':'precio', 'cleaning_fee':'gastos_limpieza', 'accommodates':'plazas', 'minimum_nights':'noches_minimas', 'review_scores_rating':'puntuacion'}, inplace = True)
# Filtramos las columnas que quermos
alojamientos = alojamientos[['id', 'anfitrion', 'url', 'tipo_alojamiento', 'distrito', 'precio', 'gastos_limpieza', 'plazas', 'noches_minimas', 'puntuacion']]
# Eliminamos las filas con valores desconocidos
alojamientos = alojamientos.dropna()
# Eliminamos el carácter $ de las columnas del precio y gastos_limpieza y las convertimos a float
alojamientos['precio'] = alojamientos.precio.str.replace(',','').str[1:].astype('float')
alojamientos['gastos_limpieza'] = alojamientos.gastos_limpieza.str[1:].astype('float')
# Creamos una nueva columna con el precio por persona multiplicando el precio diario por el número mínimo de noches, sumando los gastos de limpieza y finalmente dividiendo por el número mínimo de noches y el número de plazas.
alojamientos['precio_persona'] = (alojamientos.precio * alojamientos.noches_minimas + alojamientos.gastos_limpieza) / (alojamientos.noches_minimas + alojamientos.plazas)
alojamientos
Out[51]:
In [52]:
def tipos_alojamientos_distritos(alojamientos, distritos):
'''
Función que devuelve una serie con el porcentaje de tipos de alojamientos en una lista de distritos dada.
Parámetros:
- alojamientos: Es una lista de diccionarios, donde cada diccionario contiene los datos de un alojamiento.
- distritos: Es una lista con los nombres de los distritos.
Devuelve: Una serie con el porcentaje de tipos de alojamientos en los distritos dados.
'''
return alojamientos[alojamientos.distrito.isin(distritos)].tipo_alojamiento.value_counts(normalize = True) * 100
# Ejemplo
print(tipos_alojamientos_distritos(alojamientos, ['Arganzuela', 'Centro']))
In [53]:
def alojamientos_anfitriones_distritos(alojamientos, distritos):
'''
Función que devuelve una serie con el número de alojamientos de cada anfitrion en unos distritos dados, ordenada de mas a menos alojamientos.
Parámetros:
- alojamientos: Es una lista de diccionarios, donde cada diccionario contiene los datos de un alojamiento.
- distritos: Es una lista con los nombres de los distritos.
Devuelve: Una serie con el número de alojamientos de cada anfitrion en los distritos dados, ordenada de mas a menos alojamientos.
'''
return alojamientos[alojamientos.distrito.isin(distritos)].anfitrion.value_counts().sort_values(ascending = False)
# Ejemplo
print(alojamientos_anfitriones_distritos(alojamientos, ['Centro']))
print(alojamientos_anfitriones_distritos(alojamientos, ['Villaverde']))
In [54]:
def media_alojamientos_distritos(alojamientos):
'''
Función que devuelve una serie con el número medio de alojamientos por anfitrión de cada distrito.
Parámetros:
- alojamientos: Es una lista de diccionarios, donde cada diccionario contiene los datos de un alojamiento.
Devuelve: Una serie con el número medio de alojamientos por anfitrión de cada distrito.
'''
return alojamientos.groupby('distrito').anfitrion.value_counts().unstack(level = "distrito").mean()
# Ejemplo
print('Número medio de alojamientos por anfitrión en cada distrito')
print(media_alojamientos_distritos(alojamientos))
In [55]:
import matplotlib.pyplot as plt
def sectores_tipos_alojamientos(alojamientos, distritos):
'''
Función que dibuja un diagrama de sectores con los porcentajes de tipos de alojamientos en unos distritos dados.
Parámetros:
- alojamientos: Es una lista de diccionarios, donde cada diccionario contiene los datos de un alojamiento.
- distritos: Es una lista con los nombres de los distritos.
'''
# Definimos la figura y los ejes del gráfico
fig, ax = plt.subplots()
# Filtramos los distritos de la lista de distritos dada, después contamos la frecuencias de los tipos de alojamientos y dibujamos el diagrama de sectores
alojamientos[alojamientos.distrito.isin(distritos)].tipo_alojamiento.value_counts(normalize = True).plot(kind = 'pie', autopct='%1.0f%%', ax = ax)
# Ponermos el título
ax.set_title('Distribución del porcentaje de tipos de alojamientos\n Distritos de ' + ', '.join(distritos), loc = "center", fontdict = {'fontsize':14, 'fontweight':'bold', 'color':'tab:blue'})
# Eliminamos la etiqueta del eje y
ax.set_ylabel('')
# Guardamos el gráfico.
plt.show()
return
#Ejemplo
sectores_tipos_alojamientos(alojamientos, ['Arganzuela', 'Centro'], )
In [56]:
def barras_alojamientos_distritos(alojamientos):
'''
Función que dibuja un diagrama de barras con el número de alojamientos por distritos.
Parámetros:
- alojamientos: Es una lista de diccionarios, donde cada diccionario contiene los datos de un alojamiento.
'''
# Definimos la figura y los ejes del gráfico
fig, ax = plt.subplots()
# Contamos la frecuencias de alojamientos por distritos y dibujamos las barras.
alojamientos.distrito.value_counts().plot(kind = 'bar')
# Ponemos el título
ax.set_title('Número de alojamientos por distrito', loc = "center", fontdict = {'fontsize':14, 'fontweight':'bold', 'color':'tab:blue'})
# Ponemos una rejilla
ax.grid(axis = 'y', color = 'lightgray', linestyle = 'dashed')
# Guardamos el gráfico.
plt.show()
return
# Ejemplo
barras_alojamientos_distritos(alojamientos)
In [57]:
def barras_tipos_alojamientos_distritos(alojamientos):
'''
Función que dibuja un diagrama de barras con los porcentajes acumulados de tipos de alojamientos por distritos.
Parámetros:
- alojamientos: Es una lista de diccionarios, donde cada diccionario contiene los datos de un alojamiento.
'''
# Definimos la figura y los ejes del gráfico
fig, ax = plt.subplots()
# Agrupamos el DataFrame por distritos y contamos las frecuencias de los tipos de alojamiento. Después pivotamos el índice de los tipos de alojamientos para pasarlos a columnas y dibujamos las barras acumuladas.
(alojamientos.groupby('distrito').tipo_alojamiento.value_counts(normalize = True)*100).unstack().plot(kind = 'bar', stacked = True, ax = ax)
# Ponemos el título
ax.set_title('Tipos de alojamiento por distrito (%)', loc = "center", fontdict = {'fontsize':14, 'fontweight':'bold', 'color':'tab:blue'})
# Eliminamos la etiqueta del eje x
ax.set_xlabel('')
# Ponemos una rejilla
ax.grid(axis = 'y', color = 'lightgray', linestyle = 'dashed')
# Reducimos el eje x un 30% para que quepa la leyenda
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.7, box.height])
# Dibujar la leyenda fuera del área del gráfico
plt.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))
# Guardamos el gráfico.
plt.show()
return
# Ejemplo
barras_tipos_alojamientos_distritos(alojamientos)
In [58]:
def sectores_tipos_alojamientos_anfitrion(alojamientos, distritos, tipos):
'''
Función que dibuja un diagrama de sectores con la distribución del número de alojamientos por anfitrión de unos tipos y en unos distritos dados.
Parámetros:
- alojamientos: Es una lista de diccionarios, donde cada diccionario contiene los datos de un alojamiento.
- distritos: Es una lista con los nombres de los distritos.
- tipos: Es una lista con los nombres de los tipos de alojamientos.
'''
# Definimos la figura y los ejes del gráfico
fig, ax = plt.subplots()
# Filtramos los distritos y los tipos de alojamientos
alojamientos_filtrados = alojamientos[alojamientos.distrito.isin(distritos) & alojamientos.tipo_alojamiento.isin(tipos)]
# Contamos la frecuencia de alojamientos por anfitrión y dibujamos el diagrama de sectores
alojamientos_filtrados.anfitrion.value_counts(normalize = True).plot(kind = 'pie', ax = ax)
# Ponermos el título
ax.set_title('Distribución del número de alojamientos por anfitrión\nDistritos de ' + ', '.join(distritos) + '\nTipos de alojamiento' + ','.join(tipos), loc = "center", fontdict = {'fontsize':14, 'fontweight':'bold', 'color':'tab:blue'})
# Eliminamos la etiqueta del eje y
ax.set_ylabel('')
# Guardamos el gráfico.
plt.show()
return
# Ejemplo
sectores_tipos_alojamientos_anfitrion(alojamientos, ['Villaverde', 'Vicálvaro'], ['Entire home/apt', 'Hotel room'])
In [59]:
def barras_precios_medios_persona(alojamientos):
'''
Función que dibuja un diagrama de barras con los precios medios por persona y día de cada distrito.
Parámetros:
- alojamientos: Es una lista de diccionarios, donde cada diccionario contiene los datos de un alojamiento.
'''
# Definimos la figura y los ejes del gráfico
fig, ax = plt.subplots()
# Agrupamos por distrito, calculamos la media de precio por persona y dibujamos las barras.
alojamientos.groupby('distrito').precio_persona.mean().plot(kind = 'bar', ax = ax)
# Ponemos el título
ax.set_title('Precio medio por persona y noche', loc = "center", fontdict = {'fontsize':14, 'fontweight':'bold', 'color':'tab:blue'})
# Eliminamos la etiqueta del eje x
ax.set_xlabel('')
# Ponemos una rejilla
ax.grid(axis = 'y', color = 'lightgray', linestyle = 'dashed')
# Guardamos el gráfico.
plt.show()
return
# Ejemplo
barras_precios_medios_persona(alojamientos)
In [60]:
def precios_puntuacion_distritos(alojamientos, distritos):
'''
Función que dibuja un diagrama de dispersión con el precio por noche y persona y la puntuación en unos distritos dados.
Parámetros:
- alojamientos: Es una lista de diccionarios, donde cada diccionario contiene los datos de un alojamiento.
- distritos: Es una lista con los nombres de los distritos.
'''
# Definimos la figura y los ejes del gráfico
fig, ax = plt.subplots()
# Filtramos los distritos
alojamientos_filtrados = alojamientos[alojamientos.distrito.isin(distritos)]
# Creamos una nueva columna con el precio por persona multiplicando el precio diario por el número mínimo de noches, sumando los gastos de limpieza y finalmente dividiendo por el número mínimo de noches y el número de plazas.
alojamientos['precio_persona'] = (alojamientos.precio * alojamientos.noches_minimas + alojamientos.gastos_limpieza) / (alojamientos.noches_minimas + alojamientos.plazas)
# Dibujamos el diagrama de sipersión
ax.scatter(alojamientos['precio_persona'], alojamientos['puntuacion'])
# Ponemos el título
ax.set_title('Precios vs Puntuación\nDistritos de ' + ', '.join(distritos), loc = "center", fontdict = {'fontsize':14, 'fontweight':'bold', 'color':'tab:blue'})
# Ponemos las etiquetas de los ejes
ax.set_xlabel('Precio en €')
ax.set_ylabel('Puntuación')
# Guardamos el gráfico.
plt.show()
return
# Ejemplo
precios_puntuacion_distritos(alojamientos, ['Arganzuela', 'Centro'])
In [ ]: