The rental market in Barcelona offers a diverse array of options for guests. My analysis aims to uncover key patterns in listings across neighborhoods, room types, guest reviews, and pricing
The first visualization highlights the top 5 neighborhoods by the number of rentals. We see that neighborhoods like la Dreta de l’Eixample and el Raval dominate the market. These areas are likely central, vibrant, and tourist-friendly, offering a variety of rental options. The large number of listings in these neighborhoods may indicate high demand and a competitive market for hosts looking to attract guests.
Next, the room type distribution pie chart reveals the types of accommodations available in the city. The data shows a clear preference for entire homes/apartments and private rooms across each of the type 5 neighborhoods with a small amount of variation. This suggests that guests traveling to Barcelona often look for privacy and independence during their stay. Hosts appear to cater to this demand, offering spaces that can provide a “home away from home” experience. This is what travellers are looking for. Travellers to Barcelona are likely Families or groups wanting privacy and independence.
To explore the guest experience across neighborhoods, we examine the average reviews per month in the top 15 neighborhoods. The heatmap indicates which areas consistently receive more feedback, serving as a proxy for guest engagement and satisfaction. Interestingly, some neighborhoods with fewer listings might have higher review rates, hinting at possibly better guest experiences in those areas. For hosts, this information can guide strategies for attracting and maintaining guest satisfaction, while guests can use these insights to choose neighborhoods with highly rated stays.
The line plot delves into the relationship between the number of rentals its time of year. There appears to be a strong trend indicating that travellers tend to visit Barcelona heavily between July and September. It also shows this trend is consistent year over year. Airbnb hosts can use this information to ensure they are marketing their rentals as tourists are preparing for summer travel. They can also add different incentives for summer travellers to attract them to their rentals vs the competition.
Finally, the map paints a vivid picture of Barcelona’s rental market’s geographical spread. By overlaying the listings on a city map and highlighting our top 5 popular neighborhoods, we see how rental properties are concentrated in certain neighborhoods. 3 of the most popular neighborhoods that border the marina hold many listings as we expected to see from our first model. We also see a lot of listings just on the outskirts of those neighborhoods. The color-coded markers show a mix of options, with higher-priced listings (green and red) in low quantity, while more affordable options (blue) are more concentrated. This spatial visualization offers both guests and hosts valuable information: guests can pinpoint ideal areas for their stay, and hosts can identify potential opportunities for new listings in less saturated neighborhoods.
Conclusion
Overall, the analysis of Barcelona’s rental market reveals a dynamic environment with diverse accommodation types, varied guest engagement across neighborhoods, and a complex relationship between price and popularity. Central neighborhoods dominate the market, indicating their appeal to visitors, while room types and price points offer a range of choices catering to different preferences.
For Guests: This exploration provides insights into popular neighborhoods, room types, and value-for-money considerations to help make informed booking decisions.
For Hosts: The analysis serves as a strategic tool, highlighting areas of high demand, preferred room types, and optimal pricing strategies to maximize engagement and satisfaction.
library(ggplot2)
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(lubridate)
##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
library(geojsonio)
## Registered S3 method overwritten by 'geojsonsf':
## method from
## print.geojson geojson
##
## Attaching package: 'geojsonio'
## The following object is masked from 'package:base':
##
## pretty
library(leaflet)
listings_df <- read.csv("/Users/jordyn/Documents/R projects/Barcelonalistings.csv")
reviews_df <- read.csv("/Users/jordyn/Documents/R projects/Barcelonareviews.csv")
neighborhoods_geojson <- geojson_read("/Users/jordyn/Documents/R projects/neighbourhoods.geojson", what = "sp")
# Bar chart for the top 5 neighborhoods with the most listings
top_neighbourhoods <- listings_df %>%
count(neighbourhood) %>%
top_n(5, n) %>%
arrange(desc(n))
p1 <- ggplot(top_neighbourhoods, aes(x = reorder(neighbourhood, n), y = n)) +
geom_bar(stat = "identity", fill = "skyblue") +
coord_flip() +
labs(title = "Top 5 Neighborhoods by Number of Listings", x = "Neighborhood", y = "Number of Listings") +
theme_minimal()
p1 # Display the plot
# Pie chart: Room Type Distribution by Neighborhood
#Pie chart model
# Filter for the top 5 neighborhoods
top_neighbourhoods <- listings_df %>%
count(neighbourhood) %>%
top_n(5, n) %>%
pull(neighbourhood)
# Filter listings for only the top 5 neighborhoods
filtered_listings <- listings_df %>%
filter(neighbourhood %in% top_neighbourhoods)
# Calculate room type distribution for each neighborhood
room_type_distribution <- filtered_listings %>%
group_by(neighbourhood, room_type) %>%
summarise(count = n()) %>%
mutate(percentage = count / sum(count) * 100)
## `summarise()` has grouped output by 'neighbourhood'. You can override using the
## `.groups` argument.
p2 <- ggplot(room_type_distribution, aes(x = "", y = percentage, fill = room_type)) +
geom_bar(stat = "identity", width = 1) +
coord_polar("y", start = 0) +
labs(title = "Distribution of Room Types by Neighborhood", x = NULL, y = NULL) +
theme_void() +
theme(legend.position = "right") +
facet_wrap(~neighbourhood)
p2 # Display the plot
#Heatmap of average reviews per month by neighborhood
neighbourhood_reviews <- listings_df %>%
group_by(neighbourhood) %>%
summarise(avg_reviews = mean(reviews_per_month, na.rm = TRUE)) %>%
top_n(15, avg_reviews)
p3 <- ggplot(neighbourhood_reviews, aes(x = "", y = reorder(neighbourhood, avg_reviews), fill = avg_reviews)) +
geom_tile() +
scale_fill_gradient(low = "lightblue", high = "darkblue") +
labs(title = "Average Reviews Per Month by Neighborhood (Top 15)", x = NULL, y = "Neighborhood") +
theme_minimal()
p3 # Display the plot
# Line plot: Monthly Review Trends
#Time frame of rentals/reviews. Yearly Trend
# Convert the date column to Date type and extract the month and year
reviews_df$date <- as.Date(reviews_df$date)
reviews_df$month <- month(reviews_df$date, label = TRUE) # Extract month as a factor
reviews_df$year <- year(reviews_df$date)
# Group by month to count reviews
monthly_reviews <- reviews_df %>%
group_by(month) %>%
summarise(review_count = n())
p4 <- ggplot(monthly_reviews, aes(x = month, y = review_count)) +
geom_line(group = 1, color = "blue", size = 1.2) +
geom_point(color = "purple", size = 3) +
labs(title = "Number of Reviews by Month", x = "Month", y = "Review Count") +
theme_minimal()
p4
#Group by both year and month to analyze yearly trends
monthly_reviews_year <- reviews_df %>%
group_by(year, month) %>%
summarise(review_count = n()) %>%
ungroup()
## `summarise()` has grouped output by 'year'. You can override using the
## `.groups` argument.
# Plot the trend of reviews per month across years
p4.2 <-ggplot(monthly_reviews_year, aes(x = month, y = review_count, group = year, color = as.factor(year))) +
geom_line(size = 1.2) +
labs(title = "Number of Reviews by Month (Yearly Trend)", x = "Month", y = "Review Count", color = "Year") +
theme_minimal() +
scale_color_brewer(palette = "Set1")
p4.2
# Leaflet map: Top 5 Neighborhoods with Sample Listings
#Map
# Filter the top 5 neighborhoods from the first model
top_neighbourhoods <- listings_df %>%
count(neighbourhood) %>%
top_n(5, n) %>%
pull(neighbourhood)
# Filter the GeoJSON to include only the top 5 neighborhoods
top_neighborhoods_geojson <- neighborhoods_geojson[neighborhoods_geojson$neighbourhood %in% top_neighbourhoods, ]
# Sample 50 listings with non-missing lat/lon values
listings_sample <- listings_df %>%
filter(!is.na(longitude) & !is.na(latitude)) %>%
sample_n(100)
p5 <- leaflet() %>%
addTiles() %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addPolygons(
data = top_neighborhoods_geojson,
color = "yellow",
weight = 2,
fillOpacity = 0.1,
popup = ~neighbourhood
) %>%
addCircleMarkers(
lng = listings_sample$longitude,
lat = listings_sample$latitude,
radius = 3,
color = ifelse(listings_sample$price < 100, "blue",
ifelse(listings_sample$price < 200, "green", "red")),
popup = paste(
"Price: €", listings_sample$price, "<br>",
"Neighborhood: ", listings_sample$neighbourhood, "<br>",
"Room Type: ", listings_sample$room_type
),
fillOpacity = 0.6
)
p5 # Display the map