Analysis of AirBnb’s available in NYC by Boroughs

We will be looking at the availability of Airbnb’s in each of NYC’s Boroughs. I estimate that Manhattan will have the most.

Bar Chart by Borough

import os
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = 'c:/users/viper/Anaconda3/Library/plugins/platforms'

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import folium
import seaborn as sns
from matplotlib.ticker import FuncFormatter
import warnings

warnings.filterwarnings("ignore")
path = "c:/Users/viper/Documents/Data Visualization Data Files/"
filename = path + 'AB_NYC_2019.csv'
df = pd.read_csv(filename, usecols = ['id', 'neighbourhood_group', 'neighbourhood', 'room_type', 'price', 'minimum_nights', 'number_of_reviews'])

x = df.groupby(['neighbourhood_group']).agg({'neighbourhood_group':['count']}).reset_index()
x.columns = ['Neighbourhood', 'Count']

def pick_colors_according_to_mean_count(this_data):
    colors=[]
    avg = this_data.Count.mean()
    for each in this_data.Count:
        if each > avg*1.01:
            colors.append('green')
        elif each < avg*0.99:
            colors.append('lightcoral')
        else:
            colors.append('black')
    return colors
  
my_colors1 = pick_colors_according_to_mean_count(x)

Above = mpatches.Patch(color='green', label='Above Average')
At = mpatches.Patch(color='black', label='Within 1% of the Average')
Below = mpatches.Patch(color='lightcoral', label='Below Average')

plt.figure(figsize=(18, 10))
plt.suptitle('AirBnb Availability by Borough', fontsize=18)
plt.bar(x.loc[0:4, 'Neighbourhood'], x.loc[0:4, 'Count'], label='Count of AirBnbs by NYC Borough', color=my_colors1)
plt.legend(handles=[Above, At, Below], fontsize=14)

plt.legend(loc='upper right', fontsize=14)
plt.axhline(x.Count.mean(), color='black', linestyle='dashed')

plt.show()

Next is a line plot showcasing some pricing information

You can see how the price per night correlates with the minimum nights required.

from matplotlib.ticker import FuncFormatter

x1 = df.groupby(['minimum_nights'])['price'].mean().reset_index(name='Avg.Price')

x1 = x1.sort_values('minimum_nights', ascending=True)
x.reset_index(inplace=True, drop=True)

x1_data = x1.loc[0: 50, 'minimum_nights']
tick_interval = 5
tick_locs = [x for x in x1_data if x % tick_interval == 0]

fig = plt.figure(figsize = (18,10))
ax1 = fig.add_subplot(1, 1, 1)
ax1.plot(x1.loc[0:50, 'minimum_nights'], x1.loc[0:50, 'Avg.Price'], color='red', marker='D')
plt.xlabel('Minimum Nights')
plt.ylabel('Average Price')
plt.title('Average Price per Minimum Night', fontsize=18)
ax1.set_xlabel('Minimum Nights', fontsize=18)
ax1.set_ylabel('Avg. Price Per Night', fontsize=18)
ax1.tick_params(axis='x', labelsize=14, rotation=0)
ax1.tick_params(axis='y', labelsize=14, rotation=0)
plt.xticks(tick_locs)
ax1.yaxis.set_major_formatter( FuncFormatter( lambda x, pos:('$%1.0f')%(x)))

plt.show()

This is a geographical view of availability:

map_df = pd.read_csv(filename, usecols = ['neighbourhood_group', 'neighbourhood', 'latitude', 'longitude'])
neigh_df = map_df.groupby(['neighbourhood_group']).size().reset_index(name="Count")
nyc_geo = path + 'new-york-city-boroughs.txt'

center_of_map = [40.750580,-73.993584]   # Penn Station NYC, NY

my_map2 = folium.Map(location = center_of_map,
                   zoom_start = 10,
                   tiles = 'cartodbpositron',  
                   width = '90%',
                   height = '100%',
                   left = '5%',
                   right = '5%',
                   top = '0%')

ch_map = folium.Choropleth(geo_data = nyc_geo,
                          name = 'choropleth',
                          data = neigh_df,
                          columns = ['neighbourhood_group', 'Count'],
                          key_on = 'feature.properties.name',
                          fill_color = 'RdPu',
                          fill_opacity = 0.9,
                          line_opacity = 0.4,
                          legend_name = '# of Airbnbs that are Available',
                          highlight = True).add_to(my_map2)

#Display region/neigh label
ch_map.geojson.add_child(
    folium.features.GeoJsonTooltip(fields =['name'], aliases=['neighbourhood_group: '],
                                  labels=True, style=('background-color: black; color: white;'))

)
my_map2.save(path + 'Chloropleth_Airbnbs_NYC.html')

This is a heat map of the types of rooms available by Borough:

df_heat = pd.read_csv(filename, usecols = ['neighbourhood_group', 'room_type'])
df_heat1 = df_heat.groupby(['neighbourhood_group', 'room_type']).size().reset_index(name="Count")
hm_df = pd.pivot_table(df_heat1, index='neighbourhood_group', columns='room_type', values='Count')

fig = plt.figure(figsize=(18,10))
ax = fig.add_subplot(1, 1, 1)

comma_fmt = FuncFormatter(lambda x, p: format(int(x), ','))

ax = sns.heatmap(hm_df, linewidth = 0.2, annot = True, cmap ='coolwarm', fmt=',.0f',
                 square = True, annot_kws={'size': 11})
plt.title('Heatmap of the Different Types of Airbnbs available in each Borough', fontsize=18, pad=15)
plt.xlabel('Borough', fontsize=18, labelpad=10)
plt.ylabel('AirBnb Type', fontsize=18, labelpad=10)
plt.yticks(rotation=0, size=14)
plt.xticks(size=14)
plt.show()

Neighbourhoods in Manhattan:

df1 = pd.read_csv(filename, usecols = ['neighbourhood_group', 'neighbourhood'])
x3 = df1.groupby(['neighbourhood_group', 'neighbourhood']).size().reset_index(name="Count")
x3 = x3[x3['neighbourhood_group'] == 'Manhattan'].reset_index()

plt.figure(figsize=(18,10))

plt.scatter(x3['neighbourhood_group'], x3['neighbourhood'], marker='8', cmap='viridis', 
            c=x3['Count'], s=x3['Count'], edgecolors='black')

plt.title('Airbnbs by Neighbourhood and Borough', fontsize=18)
plt.xlabel('Borough', fontsize=14)
plt.ylabel('Neighourhoods', fontsize=14)

cbar = plt.colorbar()
cbar.set_label('Number of Airbnbs', rotation=270, fontsize=14, color='black', labelpad=30)

my_colorbar_ticks = [*range(100, int(x3['Count'].max()), 100   )]
cbar.set_ticks(my_colorbar_ticks)

my_color_bar_tick_labels = [*range(10000, int(x3['Count'].max()), 10000 )]
my_color_bar_tick_labels = [ '{:,}'.format(each) for each in my_color_bar_tick_labels]
cbar.set_ticklabels(my_color_bar_tick_labels)

plt.show()

Note that the echo = FALSE parameter was added to the code chunk to prevent printing of the R code that generated the plot.