---
title: "Lab 6: San Francisco Airbnb Listings"
output:
flexdashboard::flex_dashboard:
theme: journal
social: menu
source_code: embed
---
```{r setup, include=FALSE}
library(tidyverse)
library(sf)
library(plotly)
library(leaflet)
library(flexdashboard)
# load data
airbnb <- read_csv('/Users/joyceliu/Desktop/School/11.218/Lab 3/listingsSF.csv.gz') %>%
mutate(host_is_superhost = ifelse(!host_is_superhost | is.na(host_is_superhost), "Non-Superhost", "Superhost"))
b <- st_read('SF_Find_Neighborhoods_20251028.geojson')
# define a color palette
pal <- colorFactor(palette = c('salmon', 'gold', 'skyblue', 'orchid1'), domain = airbnb$room_type)
# define popup format
p_fmt <- paste0("<b>Name: </b>", airbnb$name, "<br>",
"<b>Host Name: </b>", airbnb$host_name,"<br>",
"<b>Nightly price: </b>", airbnb$price, "<br>")
# process data about hosts
hosts <- airbnb %>%
select(host_id, host_name, host_response_time, host_response_rate, host_is_superhost) %>%
mutate(host_response_rate = ifelse(host_response_rate == "N/A", "0", host_response_rate),
host_response_rate = as.numeric(str_replace_all(host_response_rate, "%", ""))) %>%
filter(!(host_response_time %in% c(NA, "N/A")))
hosts$host_response_time <- factor(hosts$host_response_time, levels = c("a few days or more",
"within a day",
"within a few hours",
"within an hour"))
# process data about listing size
price_beds <- airbnb %>%
select(room_type, price, beds, bedrooms) %>%
mutate(price = as.numeric(str_replace_all(price, "[$,]", ""))) %>%
filter(price < 7500)
```
Column {data-width=450}
-------------------------------------
### Chart A: Airbnb Locations in San Francisco
```{r}
leaflet() %>%
addProviderTiles(providers$CartoDB.Positron) %>%
setView(lng = -122.42, lat = 37.76, zoom = 12.4) %>%
addCircles(data = airbnb,
fillColor = ~pal(room_type),
fillOpacity = 20,
stroke = F,
radius = 10,
popup = p_fmt,
group = "Airbnb Listings") %>%
addPolygons(data = b,
color = "blue",
fill = F,
weight = 1,
group = "Neighborhood Boundary") %>%
addLegend(position = "topright",
pal = pal,
values = airbnb$room_type,
title = "Room Type") %>%
addLayersControl(overlayGroups = c("Airbnb Listings",
"Neighborhood Boundary"))
```
Column {data-width=650}
-------------------------------------
### Chart B: Response Habits of Superhosts and Non-Superhosts
```{r}
hosts %>% ggplot(aes(x = host_response_rate, fill = host_is_superhost)) +
geom_histogram(aes(y = after_stat(density))) +
facet_wrap(~host_is_superhost + host_response_time,
nrow = 2, ncol = 4,
labeller = labeller(
host_is_superhost = function(x) "",
host_response_time = function(x) str_wrap(x, width = 10)
)
) +
scale_x_continuous(labels = scales::percent_format(scale = 1)) +
scale_y_continuous(labels = scales::percent_format()) +
scale_fill_manual(values = c("darkorchid1", "palevioletred2"),
name = "") +
labs(x = "Host response rate", y = "Density") +
theme(strip.background = element_blank(),
axis.text.x = element_text(angle = 90, hjust = 1))
```
### Chart C: Price and Size of Airbnb Listings
```{r}
#| warning: false
#| message: false
price_beds %>% ggplot(aes(x = bedrooms, y = price, col = room_type)) +
geom_point(size = 1) +
geom_smooth(method = "lm", size = 0.5, se = F, fullrange = T) +
scale_color_manual(name = "Room type",
values = c('salmon', 'gold', 'skyblue', 'orchid1')) +
scale_y_continuous(labels = scales::dollar_format()) +
labs(x = "Number of bedrooms",
y = "Price per day")
```