Scatter plot menggunakan ggmap dan leaflet di R

Sebenarnya ini adalah tugas kuliah yang aku tulis ulang di blog ini agar bisa menjadi bermanfaat. Memang sebenarnya akan kesulitan untuk melakukan scatter plot ke peta kemudian diterbitkan di halaman web, tetapi adanya package ggplot dan leaflet akan sangat mempermudah untuk melakukan ini. Oiya, kita akan menggunakan R-Studio sebagai IDE.

Omong-omong, sudah lama sekali sejak aku menuliskan postingan di blog ini. Sehingga aku bahkan lupa untuk login! 😀 Konyol.

Sebelum memulai langkah-langkah selanjutnya, pastikan kamu sudah memiliki API Key untuk Google Maps.

Memuat peta King County dengan ggmap

Pada kasus ini kita akan coba menggunakan dataset House Sales in King County dari situs Kaggle. Dataset ini memiliki sekitar21613 pengamatan dengan 19 fitur. Dataset ini memiliki fitur longitude dan latitude yang akan menjadi koordinat di peta yang akan kita buat.

Pertama kita muat dulu dataset dalam format berkas csv.

rawdataset = read.csv2(file = "/home/bit/git/kuliah/dm/kc_house_data.csv", header = TRUE, sep = ",", dec = ".")

Kemudian seperti biasa, salin dulu variabelnya. Entahlah, ini lebih seperti kebiasaan daripada keharusan. Karena dengan ini, akan lebih mudah untuk mendapatkan salinan dataset yang belum diubah tanpa harus memuat ulang dengan perintah read.csv.

dataset=rawdataset

Kemudian masukan API Key untuk Google Maps, dan yang paling penting, muat package ggmap.

key = "AIzaSyBFvLBsSqNZ2p3ZsorjbtK8SB0ZyTbJMLA"
library("ggmap")

Setelah itu kita buat minimum bounding box (disebut pula sebagai bbox) pada peta King County. Kemudian dengan bbox ini, kita dapatkan irisan peta dunia pada wilayah King County saja.

ssbox = make_bbox(lon=dataset$long, lat=dataset$lat, f=0.1)
sq_map=get_map(location=ssbox, maptype = "roadmap", source="google", api_key = key)

Kemudian peta ini dapat langsung ditampilkan menggunakan ggmap

ggmap(sq_map)

Menyiapkan cluster harga rumah

Sebenarnya kita bisa langsung membuat plot posisi rumah pada peta tanpa melakukan clustering (pengelompokan) harga, tetapi informasi yang ditampilkan hanyalah posisi. Kita dapat berkreasi dengan mewarnai titik sesuai dengan kelompok harga rumah. Oleh karena itu, pertama kita buat lebih dahulu kelompok harga rumah. Kamu tentu saja bisa melakukan pengelompokan atau pengkelasan sesuai metode yang diinginkan. Saya untuk percobaan ini menggunakan algoritma kmeans. Walaupun temanku menyarankan menggunakan kmedoid untuk mengurangi dampak data pencilan.

Karena dataset tidak diurutkan berdasarkan harga, maka kita urutkan terlebih dahulu. Kemudian buat scatter plot dari harga terurut.

dataset= dataset[order(dataset$price),]
plot(dataset$price, type="o", cex=0.5)

Plot diatas kelihatannya susah dimengerti karena kurangnya keterangan penjelas. Tetapi masih dapat dimengerti bahwa sumbu X adalah index rumah yang sudah terurut dan sumbu Y adalah harga rumah. (Ya! Aku tahu ini jelek, seharusnya ada cara yang lebih baik daripada membuat plot dengan cara ini!)

Setelah itu kita lakukan pengelompokan berdasarkan harga rumah, kemudian kita tarik garis dimana pusatnya.

clusterharga = kmeans(x = dataset$price, centers = 5)
dataset$cluster = clusterharga$cluster
abline(h=clusterharga$centers, col="red")

Tadaaa! Garis merah menunjukkan 5 pusat kelompok harga. Dari situ kita lakukan binning terhadap masing-masing kelompok.

Binning

Setelah didapatkan kelompok-kelompok harga rumah, maka perlu dicari batas atas masing-masing kelompok. Batas tersebut nantinya akan digunakan untuk proses binning.

clusterupperlimit = sort(c(
max(dataset[dataset$cluster==1, "price"]),
max(dataset[dataset$cluster==2, "price"]),
max(dataset[dataset$cluster==3, "price"]),
max(dataset[dataset$cluster==4, "price"]),
max(dataset[dataset$cluster==5, "price"])
))

Jika kamu tahu cara melakukan iterasi kode diatas, silakan tinggalkan komentar. Setelah itu, kita bisa lihat batas atas dari masing-masing cluster dari variabel clusterupperlimit. Selanjutnya adalah proses binning dan gabungkan hasilnya dengan dataset.

breaks = c(-Inf, clusterupperlimit[1], clusterupperlimit[2], clusterupperlimit[3], clusterupperlimit[4], Inf)
labels = c("$", "$", "$$", "$$", "$$$")
bins = cut(x = dataset$price, breaks = breaks, labels = labels, include.lowest = TRUE, right = FALSE)
dataset <- cbind(dataset, bins)

Hasil binning tersebut bisa kita lihat dengan summary(bins) atau plot dengan ggplot.

ggplot(data=dataset, aes(x=dataset$bins,fill=..count..)) + 
geom_bar(color='black', alpha=0.9) + 
stat_count(geom="text", aes(label=..count..), hjust=-0.1) +
theme_bw() + 
labs(y="Number of Houses",x="Count") +
coord_flip() +
ylim(0,25000) +
scale_x_discrete(drop=FALSE)

Kita sudah dapatkan peta dan juga kelompok harga, langkah terakhir adalah melakukan plot ke peta.

Peta tersebut bisa disimpan dengan mealui fungsi eksport atau menggunakan perintah ggsave.

Publikasi peta ke web dengan leaflet

Jika hanya menyimpan peta ke komputer, maka langkah sebelumnya sudah cukup. Tetapi, kali ini kita ingin lebih. Dengan mempublikasi peta dengan leaflet, maka peta yang dihasilkan akan lebih interaktif. Apalagi jika kamu adalah pengembang web yang sudah biasa dengan javascript.

Pertama kita muat library dan salin dulu petanya, seperti biasa.

library("leaflet")
library("dplyr")
library("htmlwidgets")
mapdata=dataset

Kemudian karena warna yang dihasilkan ggmap terlalu cerah dan norak, kita bisa cari di internet color pallette yang lebih sedap dipandang. Beruntung saya menemukannya di sini: 36 Beautiful Color Palettes For Your Next Design Project.

colorpallete=c("#7bc043", "#0392cf", "#fdf498", "#f37736", "#ee4035")
colorlabel=c("$", "$", "$$", "$$", "$$$")
color=colorFactor(palette = colorpallete, domain = colorlabel)

Kemudian untuk menambahkan info popup ke peta yang akan dibuat, maka kita susun dahulu data yang akan kita tampilkan

mapdata % > % mutate(info=paste( " <table> <tr> <th colspan=>Information</th> </tr> <tr> <td>Class</td> <td colspan=>",bins,"</td> </tr> <tr> <td>Price</td> <td>",price/1000,"</td> <td>K USD</td> </tr> <tr> <td>Bedrooms</td> <td colspan=2>",bedrooms,"</td> </tr> <tr> <td>Bathrooms</td> <td colspan=2>",bathrooms,"</td> </tr> <tr> <td>Lot</td> <td>",sqft_lot,"</td> <td>ft2</td> </tr> <tr> <td>Living Lot</td> <td>",sqft_living,"</td> <td>ft2</td> </tr> </table> " )) -> mapdata

Setelah itu, dibuat peta menggunakan leaflet.

kingcountymaps=leaflet(data = mapdata) % > % addProviderTiles("OpenStreetMap.DE") % > % addCircleMarkers(lng = ~long, lat = ~lat, radius = 1.5, color = ~color(bins), stroke = FALSE, fillOpacity = 0.9, popup = ~info ) % > % addLegend("bottomright", colors= colorpallete, labels=colorlabel, title="Price cluster")

Kamu bisa melihat langsung peta yang telah dibuat ini dengan mengetikkan kingcountymaps di console.

Setelah semua beres, maka saatnya mengekspor petaya yang kita buat ke web dengan bantuan widgetmaker.

saveWidget(widget = kingcountymaps, file = "kingcounty.html", selfcontained = FALSE, title = "King County House Price Cluster")

Maka dihasilkan berkas html dan library pendukungya. Berkas ini disimpan di working directory yang telah kamu set.

Selanjutnya unggah berkas tersebut ke web kamu. Hasil yang aku buat bisa kamu lihat di sini: King County House Price Cluster. Aku yakin peta yang kamu buat akan lebih indah, oleh karena itu jangan lupa tinggalkan jejak di komentar.

Tambahan

1. Working directory bisa kamu atur dengan mudah melalui perintah

setwd("<path_to_folder>")

2. Peta dasar leaflet dapat diubah pada fungsi addProviderTiles Contoh peta yang tersedia ada pada Leaflet Provider Demo.

addProviderTiles("OpenStreetMap.DE")

3. Info pop-up dapat mengandung html, termasuk tabel. Oleh karena itu kamu bisa buat template-nya menggunakan tool HTML Table Generator.