Airbnb, Inc (Airbnb) adalah marketplace untuk memesan penginapan/homestay atau paket liburan, secara online melalui aplikasi. Pengguna cukup mengunduh aplikasi Airbnb melalui Google Play/Apple Store, kemudian pengguna akan mencari lokasi properti penginapan, berikut tanggal menginap. Aplikasi kemudian akan menampilkan daftar properti yang tersedia pada lokasi dan tanggal tersebut. Pengguna kemudian membayarkan fee kepada Airbnb, untuk diteruskan kepada pemilik properti. Dalam hal ini, perusahaan Airbnb tidak memiliki aset properti yang ditawarkan, namun Airbnb bertindak sebagai perantara (antara pemilik properti [host] dan pengguna). Airbnb berkantor pusat di San Fransisco, California, Amerika Serikat.
Dari properti yang tersedia di Airbnb, apakah faktor penentu harga properti di Airbnb?
SteveZheng (Steve Zheng), merupakan kontributor di Kaggle.com yang mengunggah dataset “Airbnb price prediction”. Dataset merupakan data properti Airbnb yang ada di Amerika Serikat. Dataset terdiri dari 74111 baris data, dengan 29 fitur
Deskripsi fitur-fitur yang tersedia (menurut interpretasi penulis, dikarenakan tidak adanya dokumentasi resmi dari kontributor) dan yang digunakan, adalah sebagai berikut :
| No | Feature | Description | Fitur digunakan? | Response/Predictor |
|---|---|---|---|---|
| 1 | id | Nomor ID properti | Tidak | - |
| 2 | log_price | Harga sewa properti (dalam bentuk log) | Ya | Response |
| 3 | property_type | Jenis properti (contoh : apartemen, rumah, dsb) | Ya | Predictor |
| 4 | room_type | Jenis kamar yang disewakan. Contoh : 1) entire home/apt –> seluruh rumah/apartemen, 2) private room –> kamar pribadi yang disewakan, 3) Shared room –> kamar yang dibagi dengan pengguna lain) | Ya | Predictor |
| 5 | amenities | Kelengkapan lain dari properti | Tidak | - |
| 6 | accomodates | Jumlah kapasitas orang yang dapat menginap dalam properti yang disewakan | Ya | Predictor |
| 7 | bathrooms | Jumlah kamar mandi tersedia | Ya | Predictor |
| 8 | bed_type | Jenis kasur yang disediakan : Real Bed, Futon, Pull-out Sofa, Couch atau Airbed | Ya | Predictor |
| 9 | cancellation_policy | Persyaratan pembatalan | Ya | Predictor |
| 10 | cleaning_fee | Ada atau tidaknya biaya pembersihan kamar | Ya | Predictor |
| 11 | city | Kota letak properti berada | Ya | Predictor |
| 12 | description | Deskripsi properti | Tidak | - |
| 13 | first_review | Tanggal review pertama | Ya | Predictor |
| 14 | host_has_profile_pic | Penanda apakah host menampilkan foto profil pada akun Airbnb | Tidak | - |
| 15 | host_identity_verified | Penanda apakah host telah diverifikasi oleh Airbnb | Tidak | - |
| 16 | host_response_rate | Kecepatan host dalam merespons setiap pertanyaan yang masuk | Tidak | - |
| 17 | host_since | Tanggal host mulai memasukkan propertinya pada Airbnb | Tidak | - |
| 18 | instant_bookable | Penanda apakah properti dapat langsung di book tanpa perlu adanya konfirmasi dari host | Ya | Predictor |
| 19 | last_review | Tanggal review terakhir | Tidak | - |
| 20 | latitude | Latitude lokasi properti | Ya | Predictor |
| 21 | longitude | Longitude lokasi properti | Ya | Predictor |
| 22 | name | Nama properti | Tidak | - |
| 23 | neighbourhood | nama wilayah | Tidak | - |
| 24 | number_of_reviews | jumlah review yang diberikan | Tidak | - |
| 25 | review_scores_rating | Skor review | Ya | Predictor |
| 26 | thumbnail_url | URL link gambar dari properti | Tidak | - |
| 27 | zipcode | Kodepos properti | Tidak | - |
| 28 | bedrooms | Banyak kamar tidur | Ya | Predictor |
| 29 | beds | Banyak tempat tidur yang disediakan | Ya | Predictor |
Adapun ringkasan dari nilai pada setiap feature adalah sebagai berikut :
library(tidyverse)
Registered S3 method overwritten by 'dplyr':
method from
print.rowwise_df
[30m-- [1mAttaching packages[22m --------------------------------------- tidyverse 1.2.1 --[39m
[30m[32mv[30m [34mggplot2[30m 3.2.1 [32mv[30m [34mpurrr [30m 0.3.2
[32mv[30m [34mtibble [30m 2.1.3 [32mv[30m [34mdplyr [30m 0.8.3
[32mv[30m [34mtidyr [30m 1.0.0 [32mv[30m [34mstringr[30m 1.4.0
[32mv[30m [34mreadr [30m 1.3.1 [32mv[30m [34mforcats[30m 0.4.0[39m
[30m-- [1mConflicts[22m ------------------------------------------ tidyverse_conflicts() --
[31mx[30m [34mdplyr[30m::[32mfilter()[30m masks [34mstats[30m::filter()
[31mx[30m [34mdplyr[30m::[32mlag()[30m masks [34mstats[30m::lag()[39m
airBNB<-read_csv("train.csv")
Parsed with column specification:
cols(
.default = col_character(),
id = [32mcol_double()[39m,
log_price = [32mcol_double()[39m,
accommodates = [32mcol_double()[39m,
bathrooms = [32mcol_double()[39m,
cleaning_fee = [33mcol_logical()[39m,
first_review = [34mcol_date(format = "")[39m,
host_has_profile_pic = [33mcol_logical()[39m,
host_identity_verified = [33mcol_logical()[39m,
host_since = [34mcol_date(format = "")[39m,
instant_bookable = [33mcol_logical()[39m,
last_review = [34mcol_date(format = "")[39m,
latitude = [32mcol_double()[39m,
longitude = [32mcol_double()[39m,
number_of_reviews = [32mcol_double()[39m,
review_scores_rating = [32mcol_double()[39m,
bedrooms = [32mcol_double()[39m,
beds = [32mcol_double()[39m
)
See spec(...) for full column specifications.
summary(airBNB)
id log_price property_type room_type
Min. : 344 Min. :0.000 Length:74111 Length:74111
1st Qu.: 6261964 1st Qu.:4.317 Class :character Class :character
Median :12254147 Median :4.710 Mode :character Mode :character
Mean :11266617 Mean :4.782
3rd Qu.:16402260 3rd Qu.:5.220
Max. :21230903 Max. :7.600
amenities accommodates bathrooms bed_type
Length:74111 Min. : 1.000 Min. :0.000 Length:74111
Class :character 1st Qu.: 2.000 1st Qu.:1.000 Class :character
Mode :character Median : 2.000 Median :1.000 Mode :character
Mean : 3.155 Mean :1.235
3rd Qu.: 4.000 3rd Qu.:1.000
Max. :16.000 Max. :8.000
NA's :200
cancellation_policy cleaning_fee city description
Length:74111 Mode :logical Length:74111 Length:74111
Class :character FALSE:19708 Class :character Class :character
Mode :character TRUE :54403 Mode :character Mode :character
first_review host_has_profile_pic host_identity_verified
Min. :2008-11-17 Mode :logical Mode :logical
1st Qu.:2015-06-28 FALSE:226 FALSE:24175
Median :2016-05-25 TRUE :73697 TRUE :49748
Mean :2016-01-14 NA's :188 NA's :188
3rd Qu.:2017-01-02
Max. :2017-10-05
NA's :15864
host_response_rate host_since instant_bookable last_review
Length:74111 Min. :2008-03-03 Mode :logical Min. :2009-01-21
Class :character 1st Qu.:2013-04-21 FALSE:54660 1st Qu.:2017-01-09
Mode :character Median :2014-09-28 TRUE :19451 Median :2017-04-28
Mean :2014-07-21 Mean :2017-03-14
3rd Qu.:2015-12-22 3rd Qu.:2017-09-08
Max. :2017-10-04 Max. :2017-10-05
NA's :188 NA's :15827
latitude longitude name neighbourhood
Min. :33.34 Min. :-122.51 Length:74111 Length:74111
1st Qu.:34.13 1st Qu.:-118.34 Class :character Class :character
Median :40.66 Median : -77.00 Mode :character Mode :character
Mean :38.45 Mean : -92.40
3rd Qu.:40.75 3rd Qu.: -73.95
Max. :42.39 Max. : -70.99
number_of_reviews review_scores_rating thumbnail_url zipcode
Min. : 0.0 Min. : 20.00 Length:74111 Length:74111
1st Qu.: 1.0 1st Qu.: 92.00 Class :character Class :character
Median : 6.0 Median : 96.00 Mode :character Mode :character
Mean : 20.9 Mean : 94.07
3rd Qu.: 23.0 3rd Qu.:100.00
Max. :605.0 Max. :100.00
NA's :16722
bedrooms beds
Min. : 0.000 Min. : 0.000
1st Qu.: 1.000 1st Qu.: 1.000
Median : 1.000 Median : 1.000
Mean : 1.266 Mean : 1.711
3rd Qu.: 1.000 3rd Qu.: 2.000
Max. :10.000 Max. :18.000
NA's :91 NA's :131
Dari summary diatas, diketahui bahwa terdapat beberapa feature yang memiliki nilai NA. Fitur review_scores_rating memiliki NA yang cukup tinggi. Hal ini diakibatkan karena properti tersebut belum memiliki rating. Diduga bahwa properti tersebut adalah properti baru. Oleh karena itu, dataset akan dibagi menjadi 2 cluster, yakni dataset untuk properti baru (belum pernah dipesan) dan properti lama (pernah dipesan). Adapun instance yang memiliki nilai NA untuk setiap cluster nya akan diabaikan dan tidak digunakan untuk proses pemodelan.
Dari data terdapat instance yang nilai log_price nya adalah 0. Terkait hal ini, instance tersebut tidak akan dimasukkan kedalam proses modelling
airBNB<-subset(airBNB,log_price>0)
Korelasi data numerik dapat disajikan sebagai berikut :
Dari grafik diatas, dapat terlihat bahwa log_price berkorelasi kuat dengan fitur accomodates dan bathrooms. Semakin banyak penginap yang dapat diakomodir dan semakin banyak jumlah kamar mandi, maka semakin tinggi harga sewa properti tersebut. Dalam hal ini, tidak ada pengaruh jumlah review terhadap rating score.
Secara garis besar, data yang digunakan memiliki sebaran harga sebagai berikut :
ggplot(airBNB,aes(log_price))+geom_histogram(bins=20)+labs(title = "Distribusi Harga Properti", x="Harga (dalam fungsi log)", y="Jumlah Properti")
ggplot(airBNB,aes(x=NULL, y=log_price))+geom_boxplot()+labs(title = "Distribusi Harga Properti", y="Harga (dalam fungsi log)",x=NULL)
Dari gambar terlihat bahwa harga mayoritas berada pada rentang 4.3 - 5.2
Jumlah properti berdasarkan jenis nya, dapat ditampilkan dalam grafik sebagai berikut :
ggplot(airBNB,aes(property_type))+geom_bar()+theme(axis.text.x = element_text(angle = 90))+labs(title = "Jumlah Properti berdasarkan Jenis Properti", y="Jenis Properti",x="Jumlah Properti")+ scale_x_discrete(limits=c(unique(airBNB$property_type)))
Pada grafik diatas, terlihat bahwa dataset didominasi dengan properti berjenis Apartement (apartemen) dan House (rumah). Distribusi jumlah properti berdasarkan jumlah penginap dapat digambarkan sebagai berikut :
ggplot(airBNB,aes(accommodates))+geom_bar()+theme(axis.text.x = element_text(angle = 90))+labs(title = "Distribusi Jumlah Properti berdasarkan Jumlah Penginap yang bisa Ditampung", y="Jumlah Properti",x="Jumlah Penginap") + scale_x_discrete(limits=c(1:1:16))
Dari grafik tersebut, mayoritas properti dapat menampung maksimal 2 penginap. Terdapat beberapa properti yang dapat menampung sampai 16 penginap.
Berdasarkan jumlah kamar mandi yang tersedia pada setiap properti, dapat digambarkan dalam grafik distribusi sebagai berikut :
ggplot(airBNB,aes(bathrooms))+geom_bar()+theme(axis.text.x = element_text(angle = 90))+labs(title = "Distribusi Jumlah Properti berdasarkan Jumlah Kamar Mandi", y="Jumlah Properti",x="Jumlah Kamar Mandi") + scale_x_discrete(limits=seq(from = 0, to = 8, by = 0.5))
Dari grafik dapat ditunjukkan bahwa minimal sebuah properti memiliki 1 kamar mandi. Beberapa properti memiliki kelipatan 0.5, ini artinya bahwa properti tersebut hanya memiliki kloset dan wastafel, namun tidak memiliki bath tub “what does 1 1/2 bath means?”.
Berdasarkan kota, distribusi properti dapat digambarkan sebagai berikut :
ggplot(airBNB,aes(city))+geom_bar()+theme(axis.text.x = element_text(angle = 90))+labs(title = "Distribusi Jumlah Properti berdasarkan Kota", y="Jumlah Properti",x="Kota")
Data properti yang digunakan mayoritas terletak di New York City (sebanyak lebih dari 30.000 data), sedangkan Los Angeles menempati tempat kedua. Apabila lokasi properti digambarkan dalam peta AS, maka dapat digambarkan sebagai berikut :
library(mapdata)
library(ggplot2)
library(rnaturalearth)
library(rnaturalearthdata)
library(rgeos)
library(maps)
library(sf)
library(tools)
world <- ne_countries(scale = "medium", returnclass = "sf")
sites <- data.frame(longitude = airBNB$longitude,
latitude = airBNB$latitude
)
states <- st_as_sf(map("state", plot = FALSE, fill = TRUE))
states <- cbind(states, st_coordinates(st_centroid(states)))
ggplot(data = world) +
geom_sf() +
geom_sf(data = states, fill = NA) +
geom_text(data = states, aes(X, Y, label = ID), size = 2) +
geom_point(data = sites, aes(x = longitude, y = latitude), size = 3,
shape = 16, fill = "red") +
coord_sf(xlim = c(-121, -70), ylim = c(25, 50), expand = FALSE)+
labs(title = "Sebaran Properti Airbnb pada Peta AS")
Metode yang digunakan untuk pemodelan adalah dengan menggunakan regresi linear. Dengan menggunakan software R, pemodelan ini dilakukan dengan memanggil fungsi lm(), dengan fitur price sebagai respon dan variabel lain sebagai prediktor. Nilai alpha yang digunakan untuk menguji hipotesis adalah 0.05.
Fungsi lm() di R akan otomatis mengubah fitur yang bertipe kategorikal menjadi dummy variable
Tahap pertama dilakukan subsetting terhadap dataset yang memiliki review_scores_rating lebih dari 0 (tidak NA). Data tersebut disimpan dalam variabel bernama subset_airBNB_lama
subset_airBNB_lama<-subset(airBNB,review_scores_rating>=0)
Pemodelan dibuat dengan memanggil fungsi lm() terhadap subset data properti lama
linearModel_airBNB_lama<-lm(log_price ~ property_type+room_type+accommodates+bathrooms+
bed_type+cancellation_policy+cleaning_fee+city+instant_bookable+
latitude+longitude+review_scores_rating+bedrooms+beds, data=subset_airBNB_lama)
summary(linearModel_airBNB_lama)
Dari hasil tersebut didapatkan nilai akurasi, yang diukur dengan R-squared sebesar 0.627 (62.7%). Adapun distribusi dari nilai residual dapat digambarkan sebagai berikut :
qqnorm(linearModel_airBNB_lama[["residuals"]])
qqline(linearModel_airBNB_lama[["residuals"]])
Dari grafik tersebut terlihat bahwa residual dari pemodelan linear tidak terdistribusi normal. Model kemudian diperbaiki dengan menggunakan feature selection, dengan metode forward & backward (both), dengan sintaks sebagai berikut :
library(mlbench)
library(caret)
library(MASS)
fs_both<-stepAIC(linearModel_airBNB_lama,direction = "both")
Dari proses feature selection, didapatkan hasil bahwa variabel cleaning_fee dapat diabaikan dalam pemodelan. Fitur yang sudah diseleksi kemudian dimodelkan dengan regresi linear sebagai berikut :
linearModel_airBNB_lama_fs<-lm(formula=fs_both[["terms"]],data=subset_airBNB_lama)
summary(linearModel_airBNB_lama_fs)
Namun demikian, akurasi model tetap tidak berubah, yakni berada pada 62.7%. Adapun residual dari model tidak terdistribusi normal.
qqnorm(linearModel_airBNB_lama_fs[["residuals"]])
qqline(linearModel_airBNB_lama_fs[["residuals"]])
Secara teori, apabila variabel independen bernilai 0, maka variabel dependen (log_price) akan bernilai 0. Sehingga, pemodelan dapat dilakukan dengan mengabaikan intercept.
linearModel_airBNB_lama_nointercept<-lm(log_price ~ 0+property_type+room_type+accommodates+bathrooms+
bed_type+cancellation_policy+city+instant_bookable+
latitude+longitude+review_scores_rating+bedrooms+beds, data=subset_airBNB_lama)
summary(linearModel_airBNB_lama_nointercept)
Hasilnya, terjadi peningkatan akurasi dari 62.7% menjadi 99.2%. Namun demikian, residual tetap tidak terdistribusi linear
qqnorm(linearModel_airBNB_lama_nointercept[["residuals"]])
qqline(linearModel_airBNB_lama_nointercept[["residuals"]])
Pada tahap ini dilakukan pemodelan terhadap properti baru, yakni properti yang belum memiliki rating. Langkah awal adalah dengan membuat subset atas data properti yang belum memiliki rating
subset_airBNB_baru<-subset(airBNB,is.na(review_scores_rating),)
Selanjutnya dilakukan pemodelan dengan menggunakan metode regresi linear lm(), dengan mengabaikan intercept
linearModel_airBNB_baru<-lm(log_price ~ 0+property_type+room_type+accommodates+bathrooms+
bed_type+cancellation_policy+cleaning_fee+city+instant_bookable+
latitude+longitude+bedrooms+beds, data=subset_airBNB_baru)
summary(linearModel_airBNB_baru)
Dari proses pemodelan diatas, didapatkan akurasi model sebesar 0.985 (98.5%). Bila dilakukan proses feature selection didapatkan hasil sebagai berikut :
fs_both_baru<-stepAIC(linearModel_airBNB_baru,direction = "both")
Dari hasil feature selection, didapatkan hasil bahwa model akan mengabaikan fitur bed_type. Adapun hasil regresi linear yang didapatkan sebagai berikut :
summary(fs_both_baru)
Dari hasil regresi linear dengan fitur yang sudah dilakukan seleksi, akan menghasilkan nilai akurasi yang tidak berubah, yakni sebesar 98.5%
Dari hasil pemodelan kedua subset data, yakni data properti Airbnb baru dan existing, didapatkan hasil bahwa fitur berikut mempengaruhi harga sewa properti existing :
bedrooms mempengaruhi harga propertiUntuk properti baru, fitur yang mempengaruhi, antara lain :