I decided to explore Airbnb database in New York. Using clustering methods I chose the number of clusters. Clusters were selected in both scenarios: using only locations atributes: longitude and latitude and apart from them: price and type of the rented airbnb. They made it possible to divide the acomodations in New York. In the resulting clusters, I conducted, among other statistics, an analysis of the price in the districts of New York. The main purpose is to examine the price of airbnb in clusters. We can expect that price of booking depend on its location and airbnb type as well. For example in the Manhattan district the price is supposed to be higher than in Queens or Brooklyn.
Data comes from Kaggle database. This data file includes all needed information to find out more about hosts, geographical availability, necessary metrics to make predictions and draw conclusions. I randomly selected 1000-size sample and chose variables were said to have influence on distinguishing airbnb between each other.
https://www.kaggle.com/datasets/dgomonov/new-york-city-airbnb-open-data
At the beggining, I read airbnb dataset and create and edit necessary variables.
airbnb <- read.csv("airbnb.csv")
airbnb$private_room <- airbnb$room_type
airbnb$entire_apartment <- airbnb$room_type
airbnb$shared_room <- airbnb$room_type
airbnb$private_room[airbnb$private_room == "Private room"] <- 1
airbnb$private_room[airbnb$private_room != 1] <- 0
airbnb$entire_apartment[airbnb$entire_apartment == "Entire home/apt"] <- 1
airbnb$entire_apartment[airbnb$entire_apartment != 1] <- 0
airbnb$shared_room[airbnb$shared_room == "Shared room"] <- 1
airbnb$shared_room[airbnb$shared_room != 1] <- 0
airbnb$private_room <- as.numeric(airbnb$private_room)
airbnb$entire_apartment <- as.numeric(airbnb$entire_apartment)
airbnb$shared_room <- as.numeric(airbnb$shared_room)
airbnb <- airbnb %>%
filter(price < 1000)
set.seed(200)
airbnb_sample <- airbnb[sample(nrow(airbnb), 1000), ]
set.seed(200)
airbnb_sample_ <- airbnb[sample(nrow(airbnb), 1000), ]
airbnb_map <- airbnb_sample[,c(7,8)]
airbnb2 = subset(airbnb, select=-c(id,name,host_name,host_id,last_review,calculated_host_listings_count, availability_365, neighbourhood_group,neighbourhood, room_type, reviews_per_month, minimum_nights, number_of_reviews))
airbnb2 <- scale(airbnb2)
set.seed(200)
airbnb1_sample <- airbnb2[sample(nrow(airbnb2), 1000), ]
airbnb_clus <- airbnb1_sample
To have a better visualisation, the airbnb locations are marked on the map of NY
my.sf.point <- st_as_sf(x = airbnb_map,
coords = c("longitude", "latitude"),
crs = "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")
# simple plot
# plot(my.sf.point)
# interactive map:
mapview(my.sf.point)
## Warning in cbind(`Feature ID` = fid, mat): number of rows of result is not a
## multiple of vector length (arg 1)
# convert to sp object if needed
my.sp.point <- as(my.sf.point, "Spatial")
Before clustering it is necessary to check whether the data is clusterable. Accoring to Hopkins Statisitcs equal to 0.97 I can assume that dataset is significanly a clusterable data.
get_clust_tendency(airbnb_clus, 2, graph=TRUE, gradient=list(low="red", mid="white", high="blue"))
## $hopkins_stat
## [1] 0.973009
##
## $plot
Afterwards, as it is known that we can cluster is to choose the most optimal number of clusters. I will aply clustering algorithms such as kmeans.
At the beginning, I will find the most optimal number of clusters. I will use silhouette and wss statistics and then apply it to clustering algorithms: kmeans, PAM and CLARA. I have chosen a sample consisted of 1000 observation, so the hierarchical clustering is not visable and transparent.
In the first step, the silhouette method was used to choose optimal number of clusters.The silhouette value is a measure of how similar an object is to its own cluster (cohesion) compared to other clusters (separation). The silhouette ranges from −1 to +1, where a high value indicates that the object is well matched to its own cluster and poorly matched to neighboring clusters.[wikipedia]
Kmeans charts suggests dividing data into 2 clusters. PAM method chose the 2 clusters and CLARA grouped data into 2 clusters as well. Lastly, hcut recommends 3 clusters. However, the difference in silhouette width between the two and three clusters in hcut is not so visible.
library(gridExtra)
a <- fviz_nbclust(airbnb_clus, FUNcluster = kmeans, method = "silhouette") +
labs(subtitle = "silhouette - kmeans")
b <- fviz_nbclust(airbnb_clus, FUNcluster = cluster::pam, method = "silhouette") +
labs(subtitle = "silhouette - pam")
c <- fviz_nbclust(airbnb_clus, FUNcluster = cluster::clara, method = "silhouette") +
labs(subtitle = "silhouette - clara")
d <- fviz_nbclust(airbnb_clus, FUNcluster = hcut, method = "silhouette") +
labs(subtitle = "silhouette - hcut")
grid.arrange(a, b, c, d, ncol=2)
The Squared Error for each point is the square of the distance of the point from its representation i.e. its predicted cluster center. The WSS score is the sum of these Squared Errors for all the points. [https://medium.com/analytics-vidhya/how-to-determine-the-optimal-k-for-k-means-708505d204eb]
To compare results obtained by silhouette method, I will analyze charts of elbow method with WSS. In CLARA and PAM method the end of elbow in the graph visually suggests 4 clusters. Kmeans and hcut in silhouette method suggest 3 clusters.
e1 <- fviz_nbclust(airbnb_clus, kmeans, method = "wss",k.max = 10) +
labs(subtitle = "Elbow method - kmeans")
e2 <- fviz_nbclust(airbnb_clus, clara, method = "wss",k.max = 10) +
labs(subtitle = "Elbow method - clara")
e3 <- fviz_nbclust(airbnb_clus, pam, method = "wss",k.max = 10) +
labs(subtitle = "Elbow method - pam")
e4 <- fviz_nbclust(airbnb_clus, hcut, method = "wss",k.max = 10) +
labs(subtitle = "Elbow method - hcut")
grid.arrange(e1,e2,e3,e4, ncol=2, top = "Optimal number of clusters")
library(factoextra)
cl_kmeans <- eclust(airbnb_clus, k=2, FUNcluster="kmeans", hc_metric="pearson", graph=FALSE)
a <- fviz_silhouette(cl_kmeans)
## cluster size ave.sil.width
## 1 1 473 0.43
## 2 2 527 0.47
b <- fviz_cluster(cl_kmeans, data = airbnb_clus, elipse.type = "convex") + theme_minimal()
grid.arrange(a, b, ncol=2)
The Κ-means clustering algorithm uses iterative refinement to produce a final result. The algorithm inputs are the number of clusters Κ and the data set. The data set is a collection of features for each data point. The algorithms starts with initial estimates for the Κ centroids, which can either be randomly generated or randomly selected from the data set. The algorithm then iterates between two steps: Data assigment step and Centroid update step. [https://blogs.oracle.com/ai-and-datascience/post/introduction-to-k-means-clustering]
km2 <- eclust(airbnb_clus,k=2,hc_metric = 'euclidean', graph = FALSE)
km3 <- eclust(airbnb_clus,k=3,hc_metric = 'euclidean', graph = FALSE)
km4 <- eclust(airbnb_clus,k=4,hc_metric = 'euclidean', graph = FALSE)
km5 <- eclust(airbnb_clus,k=5,hc_metric = 'euclidean', graph = FALSE)
k1 <- fviz_cluster(km2, geom = c("point")) + ggtitle('K-means with 2 clusters')
k2 <- fviz_cluster(km3, geom = c("point")) + ggtitle('K-means with 3 clusters')
k3 <- fviz_cluster(km4, geom = c("point")) + ggtitle('K-means with 4 clusters')
k4 <- fviz_cluster(km5, geom = c("point")) + ggtitle('K-means with 5 clusters')
grid.arrange(arrangeGrob(k1, k2, k3, k4, ncol=2 , top = "Clustering"))
-small datasets PAM is an implementation of the k-medoid method, i.e. a clustering technique that divides a dataset containing n objects into k groups (clusters) known a priori. A useful tool for assessing the quality of grouping is the silhouette. It is calculated for each object subject to grouping. On its basis, it is possible to determine whether the objects have been grouped correctly or whether they have been placed in the wrong clusters.
pam2 <- eclust(airbnb_clus,'pam',k=2,hc_metric = 'euclidean', graph = FALSE)
pam3 <- eclust(airbnb_clus,'pam',k=3,hc_metric = 'euclidean', graph = FALSE)
pam4 <- eclust(airbnb_clus,'pam',k=4,hc_metric = 'euclidean', graph = FALSE)
pam5<- eclust(airbnb_clus,'pam',k=5,hc_metric = 'euclidean', graph = FALSE)
p1 <- fviz_cluster(pam2, geom = c("point")) + ggtitle('PAM with 2 clusters')
p2 <- fviz_cluster(pam3, geom = c("point")) + ggtitle('PAM with 3 clusters')
p3 <- fviz_cluster(pam4, geom = c("point")) + ggtitle('PAM with 4 clusters')
p4 <- fviz_cluster(pam5, geom = c("point")) + ggtitle('PAM with 5 clusters')
grid.arrange(arrangeGrob(p1, p2, p3, p4, ncol=2 , top = "Clustering"))
-larger datasets CLARA draws multiple samples of the dataset, then applies PAM on each sample, and gives the best clustering as the oputput. [from presentation]
clara2 <- eclust(airbnb_clus,'clara',k=2,hc_metric = 'euclidean', graph = FALSE)
clara3 <- eclust(airbnb_clus,'clara',k=3,hc_metric = 'euclidean', graph = FALSE)
clara4 <- eclust(airbnb_clus,'clara',k=4,hc_metric = 'euclidean', graph = FALSE)
clara5 <- eclust(airbnb_clus,'clara',k=5,hc_metric = 'euclidean', graph = FALSE)
c1 <- fviz_cluster(clara2, geom = c("point")) + ggtitle('Clara with 2 clusters')
c2 <- fviz_cluster(clara3, geom = c("point")) + ggtitle('Clara with 3 clusters')
c3 <- fviz_cluster(clara4, geom = c("point")) + ggtitle('Clara with 4 clusters')
c4 <- fviz_cluster(clara5, geom = c("point")) + ggtitle('Clara with 5 clusters')
grid.arrange(arrangeGrob(c1, c2, c3, c4, ncol=2 , top = "Clustering"))
According to silhouete method and k-means charts, the most interesting number of clusters is 2. Moreover the size of them is similar, which cannot be said about the division in the case of 3 or 4 clusters.
km2$silinfo$clus.avg.widths
## [1] 0.4340356 0.4679409
km3$silinfo$clus.avg.widths
## [1] 0.4391868 0.4976030 0.2191956
km4$silinfo$clus.avg.widths
## [1] 0.5338543 0.3078273 0.1656116 0.4157589
km2_s <- fviz_silhouette(km2) + ggtitle('K-means with 2 clusters')
## cluster size ave.sil.width
## 1 1 473 0.43
## 2 2 527 0.47
km3_s <- fviz_silhouette(km3) + ggtitle('K-means with 3 clusters')
## cluster size ave.sil.width
## 1 1 438 0.44
## 2 2 499 0.50
## 3 3 63 0.22
km4_s <- fviz_silhouette(km4) + ggtitle('K-means with 4 clusters')
## cluster size ave.sil.width
## 1 1 418 0.53
## 2 2 48 0.31
## 3 3 64 0.17
## 4 4 470 0.42
grid.arrange(arrangeGrob(km2_s,km3_s, km4_s, ncol=2 , top = "Clustering"))
To get to know better data, I will analyze and compare data divided into 2 clusters.
km_ = kmeans(airbnb_clus, centers = 2, nstart=25)
airbnb_clus_map_ <- cbind(airbnb_sample_, cluster = km_$cluster)
new_airbnb_ <- cbind(airbnb_sample_, cluster = km_$cluster)
cluster1 <- new_airbnb_[new_airbnb_$cluster == 1,]
cluster2 <- new_airbnb_[new_airbnb_$cluster == 2,]
cluster1_map_ <- new_airbnb_[airbnb_clus_map_$cluster == 1,]
cluster2_map_ <- new_airbnb_[airbnb_clus_map_$cluster == 2,]
Cluster 1 consists of 473 airbnbs. Most of the airbnb is located in Brooklyn (46,5%). Also a relative huge group is in Manhattan district and 15,56 % of airbnb is in Queens. 454 out of 473 is private rooms. Based on summary table and density plot, mean price is around 80 dollars per night, 1st quartile is 50 and 3rd quartile is 95.
my.sf.point <- st_as_sf(x = cluster1_map_,
coords = c("longitude", "latitude"),
crs = "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")
# simple plot
# plot(my.sf.point)
# interactive map:
mapview(my.sf.point)
# convert to sp object if needed
my.sp.point <- as(my.sf.point, "Spatial")
summary(cluster1)
## id name host_id host_name
## Min. : 8025 Length:473 Min. : 7549 Length:473
## 1st Qu.:11434339 Class :character 1st Qu.: 12672019 Class :character
## Median :21261549 Mode :character Median : 40632179 Mode :character
## Mean :20266917 Mean : 78282972
## 3rd Qu.:29831517 3rd Qu.:137358866
## Max. :36477588 Max. :273139430
##
## neighbourhood_group neighbourhood latitude longitude
## Length:473 Length:473 Min. :40.58 Min. :-74.08
## Class :character Class :character 1st Qu.:40.69 1st Qu.:-73.97
## Mode :character Mode :character Median :40.72 Median :-73.95
## Mean :40.73 Mean :-73.94
## 3rd Qu.:40.76 3rd Qu.:-73.92
## Max. :40.89 Max. :-73.74
##
## room_type price minimum_nights number_of_reviews
## Length:473 Min. : 21.00 Min. : 1.000 Min. : 0.00
## Class :character 1st Qu.: 50.00 1st Qu.: 1.000 1st Qu.: 1.00
## Mode :character Median : 70.00 Median : 2.000 Median : 5.00
## Mean : 80.69 Mean : 5.307 Mean : 23.61
## 3rd Qu.: 95.00 3rd Qu.: 4.000 3rd Qu.: 24.00
## Max. :525.00 Max. :60.000 Max. :356.00
##
## last_review reviews_per_month calculated_host_listings_count
## Length:473 Min. :0.020 Min. : 1.000
## Class :character 1st Qu.:0.230 1st Qu.: 1.000
## Mode :character Median :0.860 Median : 1.000
## Mean :1.482 Mean : 3.882
## 3rd Qu.:2.110 3rd Qu.: 3.000
## Max. :9.000 Max. :103.000
## NA's :92
## availability_365 private_room entire_apartment shared_room
## Min. : 0.0 Min. :0.0000 Min. :0 Min. :0.00000
## 1st Qu.: 0.0 1st Qu.:1.0000 1st Qu.:0 1st Qu.:0.00000
## Median : 62.0 Median :1.0000 Median :0 Median :0.00000
## Mean :111.9 Mean :0.9598 Mean :0 Mean :0.04017
## 3rd Qu.:203.0 3rd Qu.:1.0000 3rd Qu.:0 3rd Qu.:0.00000
## Max. :365.0 Max. :1.0000 Max. :0 Max. :1.00000
##
## cluster
## Min. :1
## 1st Qu.:1
## Median :1
## Mean :1
## 3rd Qu.:1
## Max. :1
##
number_of_private <- filter(cluster1, room_type =='Private room')
number_of_entire <- filter(cluster1, room_type =='Entire home/apt')
number_of_shared <- filter(cluster1, room_type =='Shared room')
nrow(number_of_private)
## [1] 454
nrow(number_of_entire)
## [1] 0
nrow(number_of_shared)
## [1] 19
number_of_bronx <- filter(cluster1, neighbourhood_group =='Bronx')
number_of_manhattan <- filter(cluster1, neighbourhood_group =='Manhattan')
number_of_brooklyn <- filter(cluster1, neighbourhood_group =='Brooklyn')
number_of_queens <- filter(cluster1, neighbourhood_group =='Queens')
number_of_island <- filter(cluster1, neighbourhood_group =='Staten Island')
nrow(number_of_bronx)
## [1] 18
nrow(number_of_manhattan)
## [1] 159
nrow(number_of_brooklyn)
## [1] 220
nrow(number_of_queens)
## [1] 74
nrow(number_of_island)
## [1] 2
nrow(cluster1)
## [1] 473
mean(cluster1$price)
## [1] 80.69133
hist(cluster1$price,xlab = "Airbnb Price",col = "gray",border = "black", xlim = c(0,400) , ylim = c(0,400), breaks = 8)
d1 <- density(cluster1$price)
plot(d1)
summary(cluster1$price)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 21.00 50.00 70.00 80.69 95.00 525.00
Cluster 2 consists of 526 airbnbs. Half of the airbnb is located in Manhattan. Also a relative huge group is in Brooklyn district (37,26%) and 11,21 % of airbnb is in Queens. 526 out of 527 is ‘Entire home or apartment’. Based on summary table and density plot, mean price is around 190 dollars per night, 1st quartile is 120 and 3rd quartile is 223.5.
my.sf.point <- st_as_sf(x = cluster2_map_,
coords = c("longitude", "latitude"),
crs = "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")
# simple plot
# plot(my.sf.point)
# interactive map:
mapview(my.sf.point)
# convert to sp object if needed
my.sp.point <- as(my.sf.point, "Spatial")
summary(cluster2)
## id name host_id host_name
## Min. : 27644 Length:527 Min. : 52394 Length:527
## 1st Qu.: 8503370 Class :character 1st Qu.: 5598420 Class :character
## Median :19408844 Mode :character Median : 24467359 Mode :character
## Mean :18578594 Mean : 59844159
## 3rd Qu.:29442508 3rd Qu.: 85272560
## Max. :36404936 Max. :273568164
##
## neighbourhood_group neighbourhood latitude longitude
## Length:527 Length:527 Min. :40.51 Min. :-74.24
## Class :character Class :character 1st Qu.:40.69 1st Qu.:-73.99
## Mode :character Mode :character Median :40.73 Median :-73.96
## Mean :40.73 Mean :-73.96
## 3rd Qu.:40.76 3rd Qu.:-73.94
## Max. :40.87 Max. :-73.73
##
## room_type price minimum_nights number_of_reviews
## Length:527 Min. : 16.0 Min. : 1.000 Min. : 0.00
## Class :character 1st Qu.:120.0 1st Qu.: 2.000 1st Qu.: 1.00
## Mode :character Median :160.0 Median : 3.000 Median : 6.00
## Mean :190.1 Mean : 8.283 Mean : 25.06
## 3rd Qu.:223.5 3rd Qu.: 5.500 3rd Qu.: 25.00
## Max. :900.0 Max. :222.000 Max. :334.00
##
## last_review reviews_per_month calculated_host_listings_count
## Length:527 Min. : 0.010 Min. : 1.00
## Class :character 1st Qu.: 0.210 1st Qu.: 1.00
## Mode :character Median : 0.720 Median : 1.00
## Mean : 1.409 Mean : 12.51
## 3rd Qu.: 2.115 3rd Qu.: 2.00
## Max. :15.780 Max. :327.00
## NA's :95
## availability_365 private_room entire_apartment shared_room cluster
## Min. : 0.0 Min. :0.000000 Min. :0.0000 Min. :0 Min. :2
## 1st Qu.: 0.0 1st Qu.:0.000000 1st Qu.:1.0000 1st Qu.:0 1st Qu.:2
## Median : 44.0 Median :0.000000 Median :1.0000 Median :0 Median :2
## Mean :111.4 Mean :0.001898 Mean :0.9981 Mean :0 Mean :2
## 3rd Qu.:228.0 3rd Qu.:0.000000 3rd Qu.:1.0000 3rd Qu.:0 3rd Qu.:2
## Max. :365.0 Max. :1.000000 Max. :1.0000 Max. :0 Max. :2
##
number_of_private <- filter(cluster2, room_type =='Private room')
number_of_entire <- filter(cluster2, room_type =='Entire home/apt')
number_of_shared <- filter(cluster2, room_type =='Shared room')
nrow(number_of_private)
## [1] 1
nrow(number_of_entire)
## [1] 526
nrow(number_of_shared)
## [1] 0
number_of_bronx <- filter(cluster2, neighbourhood_group =='Bronx')
number_of_manhattan <- filter(cluster2, neighbourhood_group =='Manhattan')
number_of_brooklyn <- filter(cluster2, neighbourhood_group =='Brooklyn')
number_of_queens <- filter(cluster2, neighbourhood_group =='Queens')
number_of_island <- filter(cluster2, neighbourhood_group =='Staten Island')
nrow(number_of_bronx)
## [1] 6
nrow(number_of_manhattan)
## [1] 263
nrow(number_of_brooklyn)
## [1] 196
nrow(number_of_queens)
## [1] 59
nrow(number_of_island)
## [1] 3
nrow(cluster2)
## [1] 527
mean(cluster2$price)
## [1] 190.1347
hist(cluster2$price,xlab = "Airbnb Price",col = "gray",border = "black", xlim = c(0,400) , ylim = c(0,400), breaks = 8)
d2 <- density(cluster2$price)
plot(d2)
summary(cluster2$price)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 16.0 120.0 160.0 190.1 223.5 900.0
airbnb_sample_subset = subset(airbnb_sample,select=c(latitude, longitude))
airbnb_clus <- airbnb_sample_subset
To have a better visualisation, the airbnb locations are marked on the map of NY
my.sf.point <- st_as_sf(x = airbnb_map,
coords = c("longitude", "latitude"),
crs = "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")
# simple plot
# plot(my.sf.point)
# interactive map:
mapview(my.sf.point)
## Warning in cbind(`Feature ID` = fid, mat): number of rows of result is not a
## multiple of vector length (arg 1)
# convert to sp object if needed
my.sp.point <- as(my.sf.point, "Spatial")
Before clustering it is necessary to check whether the data is clusterable. Accoring to Hopkins Statisitcs equal to 0.95 I can assume that dataset is significanly a clusterable data.
get_clust_tendency(airbnb_clus, 2, graph=TRUE, gradient=list(low="red", mid="white", high="blue"))
## $hopkins_stat
## [1] 0.9571082
##
## $plot
Afterwards, as it is known that we can cluster is to choose the most optimal number of clusters. I will aply clustering algorithms such as kmeans.
At the beginning, I will find the most optimal number of clusters. I will use silhouette and wss statistics and then apply it to clustering algorithms: kmeans, PAM and CLARA. I have chosen a sample consisted of 1000 observation, so the hierarchical clustering is not visable and transparent.
In the first step, the silhouette method was used to choose optimal number of clusters.The silhouette value is a measure of how similar an object is to its own cluster (cohesion) compared to other clusters (separation). The silhouette ranges from −1 to +1, where a high value indicates that the object is well matched to its own cluster and poorly matched to neighboring clusters.[wikipedia]
Kmeans chart suggests dividing data into 7 clusters. PAM method chose the 5 clusters and CLARA grouped data into 4 clusters. Lastly, hcut recommends 6 clusters. However, the difference in silhouette width between the 2 and 10 clusters is not so visible in aforementioned methods.
library(gridExtra)
a <- fviz_nbclust(airbnb_clus, FUNcluster = kmeans, method = "silhouette") +
labs(subtitle = "silhouette - kmeans")
b <- fviz_nbclust(airbnb_clus, FUNcluster = cluster::pam, method = "silhouette") +
labs(subtitle = "silhouette - pam")
c <- fviz_nbclust(airbnb_clus, FUNcluster = cluster::clara, method = "silhouette") +
labs(subtitle = "silhouette - clara")
d <- fviz_nbclust(airbnb_clus, FUNcluster = hcut, method = "silhouette") +
labs(subtitle = "silhouette - hcut")
grid.arrange(a, b, c, d, ncol=2)
The Squared Error for each point is the square of the distance of the point from its representation i.e. its predicted cluster center. The WSS score is the sum of these Squared Errors for all the points. [https://medium.com/analytics-vidhya/how-to-determine-the-optimal-k-for-k-means-708505d204eb]
To compare results obtained by silhouette method, I will analyze charts of elbow method with WSS. Due to small changes in WSS between clusters, it is hard to verify the correct number of clusters. However, for each method according to elbow method, I shoyld choose 4 clusters.
e1 <- fviz_nbclust(airbnb_clus, kmeans, method = "wss",k.max = 10) +
labs(subtitle = "Elbow method - kmeans")
e2 <- fviz_nbclust(airbnb_clus, clara, method = "wss",k.max = 10) +
labs(subtitle = "Elbow method - clara")
e3 <- fviz_nbclust(airbnb_clus, pam, method = "wss",k.max = 10) +
labs(subtitle = "Elbow method - pam")
e4 <- fviz_nbclust(airbnb_clus, hcut, method = "wss",k.max = 10) +
labs(subtitle = "Elbow method - hcut")
grid.arrange(e1,e2,e3,e4, ncol=2, top = "Optimal number of clusters")
library(factoextra)
cl_kmeans <- eclust(airbnb_clus, k=4, FUNcluster="kmeans", hc_metric="pearson", graph=FALSE)
a <- fviz_silhouette(cl_kmeans)
## cluster size ave.sil.width
## 1 1 235 0.37
## 2 2 312 0.51
## 3 3 70 0.37
## 4 4 383 0.36
b <- fviz_cluster(cl_kmeans, data = airbnb_clus, elipse.type = "convex") + theme_minimal()
grid.arrange(a, b, ncol=2)
The Κ-means clustering algorithm uses iterative refinement to produce a final result. The algorithm inputs are the number of clusters Κ and the data set. The data set is a collection of features for each data point. The algorithms starts with initial estimates for the Κ centroids, which can either be randomly generated or randomly selected from the data set. The algorithm then iterates between two steps: Data assigment step and Centroid update step. [https://blogs.oracle.com/ai-and-datascience/post/introduction-to-k-means-clustering]
km4 <- eclust(airbnb_clus,k=4,hc_metric = 'euclidean', graph = FALSE)
km5 <- eclust(airbnb_clus,k=5,hc_metric = 'euclidean', graph = FALSE)
km6 <- eclust(airbnb_clus,k=6,hc_metric = 'euclidean', graph = FALSE)
k1 <- fviz_cluster(km4, geom = c("point")) + ggtitle('K-means with 4 clusters')
k2 <- fviz_cluster(km5, geom = c("point")) + ggtitle('K-means with 5 clusters')
k3 <- fviz_cluster(km6, geom = c("point")) + ggtitle('K-means with 6 clusters')
grid.arrange(arrangeGrob(k1, k2, k3, ncol=2 , top = "Clustering"))
-small datasets PAM is an implementation of the k-medoid method, i.e. a clustering technique that divides a dataset containing n objects into k groups (clusters) known a priori. A useful tool for assessing the quality of grouping is the silhouette. It is calculated for each object subject to grouping. On its basis, it is possible to determine whether the objects have been grouped correctly or whether they have been placed in the wrong clusters.
pam4 <- eclust(airbnb_clus,'pam',k=4,hc_metric = 'euclidean', graph = FALSE)
pam5<- eclust(airbnb_clus,'pam',k=5,hc_metric = 'euclidean', graph = FALSE)
pam6 <- eclust(airbnb_clus,'pam',k=6,hc_metric = 'euclidean', graph = FALSE)
p1 <- fviz_cluster(pam4, geom = c("point")) + ggtitle('PAM with 4 clusters')
p2 <- fviz_cluster(pam5, geom = c("point")) + ggtitle('PAM with 5 clusters')
p3 <- fviz_cluster(pam6, geom = c("point")) + ggtitle('PAM with 6 clusters')
grid.arrange(arrangeGrob(p1, p2, p3, ncol=2 , top = "Clustering"))
-larger datasets CLARA draws multiple samples of the dataset, then applies PAM on each sample, and gives the best clustering as the oputput. [from presentation]
clara4 <- eclust(airbnb_clus,'clara',k=4,hc_metric = 'euclidean', graph = FALSE)
clara5 <- eclust(airbnb_clus,'clara',k=5,hc_metric = 'euclidean', graph = FALSE)
clara6 <- eclust(airbnb_clus,'clara',k=6,hc_metric = 'euclidean', graph = FALSE)
c1 <- fviz_cluster(clara4, geom = c("point")) + ggtitle('Clara with 4 clusters')
c2 <- fviz_cluster(clara5, geom = c("point")) + ggtitle('Clara with 5 clusters')
c3 <- fviz_cluster(clara6, geom = c("point")) + ggtitle('Clara with 6 clusters')
grid.arrange(arrangeGrob(c1, c2, c3, ncol=2 , top = "Clustering"))
km4$silinfo$clus.avg.widths
## [1] 0.3738984 0.5111021 0.3655410 0.3590772
km5$silinfo$clus.avg.widths
## [1] 0.3656397 0.4962927 0.3640703 0.3576738 0.4113436
km6$silinfo$clus.avg.widths
## [1] 0.4430948 0.5222087 0.2732862 0.4301002 0.4937648 0.1974620
km4_s <- fviz_silhouette(km4) + ggtitle('K-means with 4 clusters')
## cluster size ave.sil.width
## 1 1 235 0.37
## 2 2 312 0.51
## 3 3 70 0.37
## 4 4 383 0.36
km5_s <- fviz_silhouette(km5) + ggtitle('K-means with 5 clusters')
## cluster size ave.sil.width
## 1 1 217 0.37
## 2 2 298 0.50
## 3 3 40 0.36
## 4 4 382 0.36
## 5 5 63 0.41
km6_s <- fviz_silhouette(km6) + ggtitle('K-means with 6 clusters')
## cluster size ave.sil.width
## 1 1 167 0.44
## 2 2 287 0.52
## 3 3 52 0.27
## 4 4 293 0.43
## 5 5 78 0.49
## 6 6 123 0.20
grid.arrange(arrangeGrob(km4_s,km5_s, km6_s, ncol=2 , top = "Clustering"))
Taking into consideration all aforementioned methods, I eventually chose 4 clusters. Below I am joining two tabels to see cluster1, cluster2, cluster3 and cluster4 statistics to compare them.
km_ = kmeans(airbnb_clus, centers = 4, nstart=25)
airbnb_clus_map_ <- cbind(airbnb_sample_, cluster = km_$cluster)
new_airbnb_ <- cbind(airbnb_sample_, cluster = km_$cluster)
cluster1 <- new_airbnb_[new_airbnb_$cluster == 1,]
cluster2 <- new_airbnb_[new_airbnb_$cluster == 2,]
cluster3 <- new_airbnb_[new_airbnb_$cluster == 3,]
cluster4 <- new_airbnb_[new_airbnb_$cluster == 4,]
cluster1_map_ <- new_airbnb_[airbnb_clus_map_$cluster == 1,]
cluster2_map_ <- new_airbnb_[airbnb_clus_map_$cluster == 2,]
cluster3_map_ <- new_airbnb_[airbnb_clus_map_$cluster == 3,]
cluster4_map_ <- new_airbnb_[airbnb_clus_map_$cluster == 4,]
Cluster 1 consists of 231 airbnbs. Most of the airbnb is located in Manhattan (70%). The rest aribnbs are located in Queens. Based on summary table and density plot, mean price is around 125 dollars per night, 1st quartile is 25 and 3rd quartile is 150. 103 airbnbs are clasified as ‘entire apartemnt’ and 123 of them are private rooms.
my.sf.point <- st_as_sf(x = cluster1_map_,
coords = c("longitude", "latitude"),
crs = "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")
# simple plot
# plot(my.sf.point)
# interactive map:
mapview(my.sf.point)
# convert to sp object if needed
my.sp.point <- as(my.sf.point, "Spatial")
nrow(cluster1)
## [1] 231
summary(cluster1)
## id name host_id host_name
## Min. : 9518 Length:231 Min. : 31374 Length:231
## 1st Qu.: 8832204 Class :character 1st Qu.: 9398728 Class :character
## Median :18503701 Mode :character Median : 32625342 Mode :character
## Mean :18772126 Mean : 70102918
## 3rd Qu.:28868838 3rd Qu.:113395182
## Max. :36477588 Max. :272557714
##
## neighbourhood_group neighbourhood latitude longitude
## Length:231 Length:231 Min. :40.74 Min. :-73.98
## Class :character Class :character 1st Qu.:40.77 1st Qu.:-73.96
## Mode :character Mode :character Median :40.80 Median :-73.94
## Mean :40.80 Mean :-73.94
## 3rd Qu.:40.82 3rd Qu.:-73.92
## Max. :40.89 Max. :-73.85
##
## room_type price minimum_nights number_of_reviews
## Length:231 Min. : 25.0 Min. : 1.000 Min. : 0.00
## Class :character 1st Qu.: 66.5 1st Qu.: 1.000 1st Qu.: 1.00
## Mode :character Median : 99.0 Median : 2.000 Median : 6.00
## Mean :124.6 Mean : 6.294 Mean : 21.09
## 3rd Qu.:150.0 3rd Qu.: 5.000 3rd Qu.: 21.00
## Max. :900.0 Max. :122.000 Max. :268.00
##
## last_review reviews_per_month calculated_host_listings_count
## Length:231 Min. :0.020 Min. : 1.000
## Class :character 1st Qu.:0.210 1st Qu.: 1.000
## Mode :character Median :0.710 Median : 1.000
## Mean :1.351 Mean : 3.926
## 3rd Qu.:2.030 3rd Qu.: 2.000
## Max. :9.000 Max. :103.000
## NA's :48
## availability_365 private_room entire_apartment shared_room
## Min. : 0.0 Min. :0.0000 Min. :0.0000 Min. :0.00000
## 1st Qu.: 0.0 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:0.00000
## Median : 33.0 Median :1.0000 Median :0.0000 Median :0.00000
## Mean :109.9 Mean :0.5325 Mean :0.4459 Mean :0.02165
## 3rd Qu.:242.5 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:0.00000
## Max. :365.0 Max. :1.0000 Max. :1.0000 Max. :1.00000
##
## cluster
## Min. :1
## 1st Qu.:1
## Median :1
## Mean :1
## 3rd Qu.:1
## Max. :1
##
number_of_private <- filter(cluster1, room_type =='Private room')
number_of_entire <- filter(cluster1, room_type =='Entire home/apt')
number_of_shared <- filter(cluster1, room_type =='Shared room')
nrow(number_of_private)
## [1] 123
nrow(number_of_entire)
## [1] 103
nrow(number_of_shared)
## [1] 5
number_of_bronx <- filter(cluster1, neighbourhood_group =='Bronx')
number_of_manhattan <- filter(cluster1, neighbourhood_group =='Manhattan')
number_of_brooklyn <- filter(cluster1, neighbourhood_group =='Brooklyn')
number_of_queens <- filter(cluster1, neighbourhood_group =='Queens')
number_of_island <- filter(cluster1, neighbourhood_group =='Staten Island')
nrow(number_of_bronx)
## [1] 19
nrow(number_of_manhattan)
## [1] 162
nrow(number_of_brooklyn)
## [1] 0
nrow(number_of_queens)
## [1] 50
nrow(number_of_island)
## [1] 0
mean(cluster1$price)
## [1] 124.5714
hist(cluster1$price,xlab = "Airbnb Price",col = "gray",border = "black", xlim = c(0,400) , ylim = c(0,200), breaks = 8)
d1 <- density(cluster1$price)
plot(d1)
summary(cluster1$price)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 25.0 66.5 99.0 124.6 150.0 900.0
Cluster 2 consists of 70 airbnbs. Most of the airbnb is located in East Queens (93%). The rest aribnbs are located in Bronx Based on summary table and density plot, mean price is around 90 dollars per night, 1st quartile is 50 and 3rd quartile is 100. 32 airbnbs are clasified as ‘entire apartemnt’ and 38 of them are private rooms.
my.sf.point <- st_as_sf(x = cluster2_map_,
coords = c("longitude", "latitude"),
crs = "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")
# simple plot
# plot(my.sf.point)
# interactive map:
mapview(my.sf.point)
# convert to sp object if needed
my.sp.point <- as(my.sf.point, "Spatial")
nrow(cluster2)
## [1] 70
summary(cluster2)
## id name host_id host_name
## Min. : 765563 Length:70 Min. : 445894 Length:70
## 1st Qu.:17410253 Class :character 1st Qu.: 23425614 Class :character
## Median :26764064 Mode :character Median : 94315680 Mode :character
## Mean :24049823 Mean :106834910
## 3rd Qu.:31906802 3rd Qu.:183438968
## Max. :36412355 Max. :263504959
##
## neighbourhood_group neighbourhood latitude longitude
## Length:70 Length:70 Min. :40.58 Min. :-73.89
## Class :character Class :character 1st Qu.:40.71 1st Qu.:-73.86
## Mode :character Mode :character Median :40.73 Median :-73.83
## Mean :40.73 Mean :-73.83
## 3rd Qu.:40.76 3rd Qu.:-73.80
## Max. :40.86 Max. :-73.73
##
## room_type price minimum_nights number_of_reviews
## Length:70 Min. : 28.00 Min. : 1.000 Min. : 0.0
## Class :character 1st Qu.: 50.00 1st Qu.: 1.000 1st Qu.: 4.0
## Mode :character Median : 65.00 Median : 2.000 Median : 12.0
## Mean : 89.69 Mean : 4.557 Mean : 30.4
## 3rd Qu.: 99.75 3rd Qu.: 3.000 3rd Qu.: 37.0
## Max. :359.00 Max. :60.000 Max. :356.0
##
## last_review reviews_per_month calculated_host_listings_count
## Length:70 Min. : 0.0200 Min. : 1.0
## Class :character 1st Qu.: 0.6675 1st Qu.: 1.0
## Mode :character Median : 1.8800 Median : 2.0
## Mean : 2.5628 Mean : 4.9
## 3rd Qu.: 3.2800 3rd Qu.: 4.0
## Max. :15.7800 Max. :103.0
## NA's :10
## availability_365 private_room entire_apartment shared_room cluster
## Min. : 0.0 Min. :0.0000 Min. :0.0000 Min. :0 Min. :2
## 1st Qu.: 58.0 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:0 1st Qu.:2
## Median :134.5 Median :1.0000 Median :0.0000 Median :0 Median :2
## Mean :157.3 Mean :0.5429 Mean :0.4571 Mean :0 Mean :2
## 3rd Qu.:282.5 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:0 3rd Qu.:2
## Max. :365.0 Max. :1.0000 Max. :1.0000 Max. :0 Max. :2
##
number_of_private <- filter(cluster2, room_type =='Private room')
number_of_entire <- filter(cluster2, room_type =='Entire home/apt')
number_of_shared <- filter(cluster2, room_type =='Shared room')
nrow(number_of_private)
## [1] 38
nrow(number_of_entire)
## [1] 32
nrow(number_of_shared)
## [1] 0
number_of_bronx <- filter(cluster2, neighbourhood_group =='Bronx')
number_of_manhattan <- filter(cluster2, neighbourhood_group =='Manhattan')
number_of_brooklyn <- filter(cluster2, neighbourhood_group =='Brooklyn')
number_of_queens <- filter(cluster2, neighbourhood_group =='Queens')
number_of_island <- filter(cluster2, neighbourhood_group =='Staten Island')
nrow(number_of_bronx)
## [1] 5
nrow(number_of_manhattan)
## [1] 0
nrow(number_of_brooklyn)
## [1] 0
nrow(number_of_queens)
## [1] 65
nrow(number_of_island)
## [1] 0
mean(cluster2$price)
## [1] 89.68571
hist(cluster2$price,xlab = "Airbnb Price",col = "gray",border = "black", xlim = c(0,1000) , ylim = c(0,100), breaks = 4)
d2 <- density(cluster2$price)
plot(d2)
summary(cluster2$price)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 28.00 50.00 65.00 89.69 99.75 359.00
Cluster 1 consists of 378 airbnbs. Most of the airbnb is located in Brooklyn (98%). Based on summary table and density plot, mean price is around 114 dollars per night, 1st quartile is 60 and 3rd quartile is 139. 199 airbnbs are clasified as ‘entire apartemnt’ and 171 of them are private rooms.
my.sf.point <- st_as_sf(x = cluster3_map_,
coords = c("longitude", "latitude"),
crs = "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")
# simple plot
# plot(my.sf.point)
# interactive map:
mapview(my.sf.point)
# convert to sp object if needed
my.sp.point <- as(my.sf.point, "Spatial")
nrow(cluster3)
## [1] 378
summary(cluster3)
## id name host_id host_name
## Min. : 8025 Length:378 Min. : 22486 Length:378
## 1st Qu.: 9799367 Class :character 1st Qu.: 6070007 Class :character
## Median :20332798 Mode :character Median : 27250906 Mode :character
## Mean :19534555 Mean : 63309123
## 3rd Qu.:29323210 3rd Qu.: 90805038
## Max. :36351543 Max. :273139430
##
## neighbourhood_group neighbourhood latitude longitude
## Length:378 Length:378 Min. :40.51 Min. :-74.24
## Class :character Class :character 1st Qu.:40.67 1st Qu.:-73.97
## Mode :character Mode :character Median :40.69 Median :-73.95
## Mean :40.68 Mean :-73.95
## 3rd Qu.:40.70 3rd Qu.:-73.93
## Max. :40.72 Max. :-73.88
##
## room_type price minimum_nights number_of_reviews
## Length:378 Min. : 21.0 Min. : 1.000 Min. : 0.00
## Class :character 1st Qu.: 60.0 1st Qu.: 1.000 1st Qu.: 1.00
## Mode :character Median : 90.0 Median : 2.000 Median : 6.00
## Mean :114.4 Mean : 5.847 Mean : 23.94
## 3rd Qu.:139.0 3rd Qu.: 4.750 3rd Qu.: 24.00
## Max. :900.0 Max. :222.000 Max. :323.00
##
## last_review reviews_per_month calculated_host_listings_count
## Length:378 Min. :0.010 Min. : 1.000
## Class :character 1st Qu.:0.220 1st Qu.: 1.000
## Mode :character Median :0.780 Median : 1.000
## Mean :1.417 Mean : 2.548
## 3rd Qu.:2.150 3rd Qu.: 2.000
## Max. :8.970 Max. :43.000
## NA's :61
## availability_365 private_room entire_apartment shared_room
## Min. : 0.0 Min. :0.0000 Min. :0.0000 Min. :0.00000
## 1st Qu.: 0.0 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:0.00000
## Median : 54.5 Median :1.0000 Median :0.0000 Median :0.00000
## Mean :108.4 Mean :0.5265 Mean :0.4524 Mean :0.02116
## 3rd Qu.:217.0 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:0.00000
## Max. :365.0 Max. :1.0000 Max. :1.0000 Max. :1.00000
##
## cluster
## Min. :3
## 1st Qu.:3
## Median :3
## Mean :3
## 3rd Qu.:3
## Max. :3
##
number_of_private <- filter(cluster3, room_type =='Private room')
number_of_entire <- filter(cluster3, room_type =='Entire home/apt')
number_of_shared <- filter(cluster3, room_type =='Shared room')
nrow(number_of_private)
## [1] 199
nrow(number_of_entire)
## [1] 171
nrow(number_of_shared)
## [1] 8
number_of_bronx <- filter(cluster3, neighbourhood_group =='Bronx')
number_of_manhattan <- filter(cluster3, neighbourhood_group =='Manhattan')
number_of_brooklyn <- filter(cluster3, neighbourhood_group =='Brooklyn')
number_of_queens <- filter(cluster3, neighbourhood_group =='Queens')
number_of_island <- filter(cluster3, neighbourhood_group =='Staten Island')
nrow(number_of_bronx)
## [1] 0
nrow(number_of_manhattan)
## [1] 0
nrow(number_of_brooklyn)
## [1] 367
nrow(number_of_queens)
## [1] 6
nrow(number_of_island)
## [1] 5
mean(cluster3$price)
## [1] 114.3757
hist(cluster3$price, xlim = c(0,500) , ylim = c(0,400))
d3 <- density(cluster3$price)
plot(d3)
summary(cluster3$price)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 21.0 60.0 90.0 114.4 139.0 900.0
Cluster 4 consists of 321 airbnbs. Most of the airbnb is located in Manhattan (81%). 15% aribnbs are located in North West Brooklyn. Based on summary table and density plot, mean price is around 187 dollars per night, 1st quartile is 105 and 3rd quartile is 225. 220 airbnbs are clasified as ‘entire apartemnt’ and 95 of them are private rooms.
my.sf.point <- st_as_sf(x = cluster4_map_,
coords = c("longitude", "latitude"),
crs = "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")
# simple plot
# plot(my.sf.point)
# interactive map:
mapview(my.sf.point)
# convert to sp object if needed
my.sp.point <- as(my.sf.point, "Spatial")
nrow(cluster4)
## [1] 321
summary(cluster4)
## id name host_id host_name
## Min. : 12048 Length:321 Min. : 7549 Length:321
## 1st Qu.: 8615062 Class :character 1st Qu.: 7339399 Class :character
## Median :19413230 Mode :character Median : 30933227 Mode :character
## Mean :18608288 Mean : 65304210
## 3rd Qu.:29704596 3rd Qu.:107434423
## Max. :36426720 Max. :273568164
##
## neighbourhood_group neighbourhood latitude longitude
## Length:321 Length:321 Min. :40.69 Min. :-74.02
## Class :character Class :character 1st Qu.:40.72 1st Qu.:-74.00
## Mode :character Mode :character Median :40.73 Median :-73.99
## Mean :40.74 Mean :-73.98
## 3rd Qu.:40.75 3rd Qu.:-73.98
## Max. :40.78 Max. :-73.92
##
## room_type price minimum_nights number_of_reviews
## Length:321 Min. : 16.0 Min. : 1.000 Min. : 0.00
## Class :character 1st Qu.:105.0 1st Qu.: 2.000 1st Qu.: 1.00
## Mode :character Median :160.0 Median : 3.000 Median : 4.00
## Mean :187.2 Mean : 9.009 Mean : 25.94
## 3rd Qu.:225.0 3rd Qu.: 7.000 3rd Qu.: 26.00
## Max. :900.0 Max. :180.000 Max. :334.00
##
## last_review reviews_per_month calculated_host_listings_count
## Length:321 Min. :0.020 Min. : 1.00
## Class :character 1st Qu.:0.160 1st Qu.: 1.00
## Mode :character Median :0.660 Median : 1.00
## Mean :1.278 Mean : 19.37
## 3rd Qu.:1.950 3rd Qu.: 2.00
## Max. :6.430 Max. :327.00
## NA's :68
## availability_365 private_room entire_apartment shared_room
## Min. : 0.0 Min. :0.000 Min. :0.0000 Min. :0.00000
## 1st Qu.: 0.0 1st Qu.:0.000 1st Qu.:0.0000 1st Qu.:0.00000
## Median : 28.0 Median :0.000 Median :1.0000 Median :0.00000
## Mean :106.7 Mean :0.296 Mean :0.6854 Mean :0.01869
## 3rd Qu.:207.0 3rd Qu.:1.000 3rd Qu.:1.0000 3rd Qu.:0.00000
## Max. :365.0 Max. :1.000 Max. :1.0000 Max. :1.00000
##
## cluster
## Min. :4
## 1st Qu.:4
## Median :4
## Mean :4
## 3rd Qu.:4
## Max. :4
##
number_of_private <- filter(cluster4, room_type =='Private room')
number_of_entire <- filter(cluster4, room_type =='Entire home/apt')
number_of_shared <- filter(cluster4, room_type =='Shared room')
nrow(number_of_private)
## [1] 95
nrow(number_of_entire)
## [1] 220
nrow(number_of_shared)
## [1] 6
number_of_bronx <- filter(cluster4, neighbourhood_group =='Bronx')
number_of_manhattan <- filter(cluster4, neighbourhood_group =='Manhattan')
number_of_brooklyn <- filter(cluster4, neighbourhood_group =='Brooklyn')
number_of_queens <- filter(cluster4, neighbourhood_group =='Queens')
number_of_island <- filter(cluster4, neighbourhood_group =='Staten Island')
nrow(number_of_bronx)
## [1] 0
nrow(number_of_manhattan)
## [1] 260
nrow(number_of_brooklyn)
## [1] 49
nrow(number_of_queens)
## [1] 12
nrow(number_of_island)
## [1] 0
mean(cluster4$price)
## [1] 187.1651
hist(cluster4$price, xlim = c(0,300) , ylim = c(0,500))
d4 <- density(cluster4$price)
plot(d4)
summary(cluster4$price)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 16.0 105.0 160.0 187.2 225.0 900.0
clustering on locations, price and type of airbnb The algorithms like K-means, PAM, CLARA suggested dividing data into 4-7 clusters depending on the method. However, basing on silhouette method, average silhouette width increases slightly, increasing number of clusters from 4. Thus, after analyzing created plots, I chose 4 clusters. Unfortunately, Hierarchical Clustering is not so helpful, as the dataset is quite huge.
Comparing two scenarios, even though clustering on locations, price and type only have 2 clusters, clusters are divided in a significant way. Whereas, as expected, clustering by location is very successful in dividing the data into New York City districts. So we can compare prices and airbnb locations in 4 areas that can be considered as NY districts