Tutorial Web Scrape Menggunakan R: Situs Informasi SDM Kesehatan Kemenkes (bagian I)
Sebagaimana kita ketahui bersama, beberapa saat lalu terjadi kekisruhan di kalangan pejabat terkait data tenaga kesehatan (khususnya dokter) yang ada di Indonesia.
Memangnya di mana sih kita bisa mendapatkan data update terkait banyaknya tenaga kesehatan di Indonesia?
Salah satu sumber terpercaya yang bisa kita percaya adalah situs Badan PPSDM Kemenkes.
Keterangan gambar: Data provinsi bisa di- drill down sampai level kabupaten dan kota.
Kalau kita perhatikan baik-baik, bentuk data yang disajikan dalam website tersebut sudah berbentuk tabel. Walaupun kita bisa dengan mudah men-download datanya dalam bentuk Ms. Excel, tapi akan sangat menguntungkan jika kita melakukan web scraping dengan R.
Lho kok malah begitu?
Jika kita ingin melakukan scraping secara otomatis untuk semua data yang ada di sana (termasuk data kota dan kabupaten), membuat algoritma scraping dan menggabungkan semua datanya adalah langkah yang paling cepat dan tepat.
Langkah Web Scraping dengan R
Web scraping dengan menggunakan R setidaknya bisa dilakukan dengan
2
cara, yakni:
- Menggunakan
library(rvest)
, menargetkan isicss
darihtml doc
suatu webpages. - Menggunakan
library(Rselenium)
, menggunakan prinsip mimic apa yang kita lakukan di web browser.
Sekarang, saya akan gunakan prinsip library(rvest)
untuk mengambil
website berisi tabel. Caranya sangatlah mudah, cukup dengan
menggunakan html_table()
saja.
Kira-kira begini workflow-nya:
Web Scrape untuk Informasi Provinsi
Saya akan tunjukkan cara melakukan web scraping pada situs informasi provinsi sebagai berikut:
# tahap 1
# load libraries yang dibutuhkan
library(rvest)
library(dplyr)
# tahap 2
# simpan url target
url = "http://bppsdmk.kemkes.go.id/info_sdmk/info/index?rumpun=101"
# tahap 3
# lakukan scrape tabel
data = read_html(url) %>% html_table(fill = T)
Data tabel sudah berhasil kita scrape. Mari kita lihat dulu struktur
dari data
tersebut:
str(data)
## List of 1
## $ :'data.frame': 36 obs. of 9 variables:
## ..$ No. : chr [1:36] "No." "1" "2" "3" ...
## ..$ Nama Provinsi : chr [1:36] "Nama Provinsi" "ACEH" "SUMATERA UTARA" "SUMATERA BARAT" ...
## ..$ Jumlah Unit : chr [1:36] "Jumlah Unit" "447" "827" "426" ...
## ..$ Jumlah Tenaga Medis : chr [1:36] "Dokter Umum" "1556" "3097" "1279" ...
## ..$ Jumlah Tenaga Medis : chr [1:36] "Jumlah Tenaga Medis" "375" "768" "446" ...
## ..$ Jumlah Tenaga Medis : chr [1:36] "Dokter Gigi" "806" "1817" "838" ...
## ..$ Jumlah Tenaga Medis : chr [1:36] "Dokter Spesialis" "16" "59" "14" ...
## ..$ Jumlah Tenaga Medis : chr [1:36] "Dokter Sub Spesialis" "22" "51" "20" ...
## ..$ Jumlah (Per Provinsi): chr [1:36] "Dokter Gigi Spesialis & Dokter Gigi Sub Spesialis" "2775" "5792" "2597" ...
Ternyata data
berbentuk list berisi satu element saja berbentuk
data.frame. Kita cukup mengambil element pertama dari list
tersebut.
data = data[[1]]
Kita cek kembali struktur datanya:
str(data)
## 'data.frame': 36 obs. of 9 variables:
## $ No. : chr "No." "1" "2" "3" ...
## $ Nama Provinsi : chr "Nama Provinsi" "ACEH" "SUMATERA UTARA" "SUMATERA BARAT" ...
## $ Jumlah Unit : chr "Jumlah Unit" "447" "827" "426" ...
## $ Jumlah Tenaga Medis : chr "Dokter Umum" "1556" "3097" "1279" ...
## $ Jumlah Tenaga Medis : chr "Jumlah Tenaga Medis" "375" "768" "446" ...
## $ Jumlah Tenaga Medis : chr "Dokter Gigi" "806" "1817" "838" ...
## $ Jumlah Tenaga Medis : chr "Dokter Spesialis" "16" "59" "14" ...
## $ Jumlah Tenaga Medis : chr "Dokter Sub Spesialis" "22" "51" "20" ...
## $ Jumlah (Per Provinsi): chr "Dokter Gigi Spesialis & Dokter Gigi Sub Spesialis" "2775" "5792" "2597" ...
Nah, sekarang data
kita sudah berbentuk data.frame. Mari kita
lihat bagaimana isinya:
No. | Nama Provinsi | Jumlah Unit | Jumlah Tenaga Medis | Jumlah Tenaga Medis | Jumlah Tenaga Medis | Jumlah Tenaga Medis | Jumlah Tenaga Medis | Jumlah (Per Provinsi) |
---|---|---|---|---|---|---|---|---|
No. | Nama Provinsi | Jumlah Unit | Dokter Umum | Jumlah Tenaga Medis | Dokter Gigi | Dokter Spesialis | Dokter Sub Spesialis | Dokter Gigi Spesialis & Dokter Gigi Sub Spesialis |
1 | ACEH | 447 | 1556 | 375 | 806 | 16 | 22 | 2775 |
2 | SUMATERA UTARA | 827 | 3097 | 768 | 1817 | 59 | 51 | 5792 |
3 | SUMATERA BARAT | 426 | 1279 | 446 | 838 | 14 | 20 | 2597 |
4 | RIAU | 402 | 1452 | 428 | 622 | 23 | 15 | 2540 |
5 | JAMBI | 615 | 892 | 234 | 382 | 5 | 21 | 1534 |
6 | SUMATERA SELATAN | 463 | 1239 | 280 | 792 | 48 | 34 | 2393 |
7 | BENGKULU | 332 | 454 | 134 | 208 | 0 | 7 | 803 |
8 | LAMPUNG | 493 | 1346 | 197 | 691 | 7 | 15 | 2256 |
9 | KEPULAUAN BANGKA BELITUNG | 280 | 532 | 105 | 202 | 2 | 13 | 854 |
10 | KEPULAUAN RIAU | 185 | 620 | 162 | 361 | 5 | 27 | 1175 |
11 | DKI JAKARTA | 3193 | 6602 | 1972 | 6620 | 545 | 781 | 16520 |
12 | JAWA BARAT | 4645 | 5917 | 1519 | 3573 | 49 | 228 | 11286 |
13 | JAWA TENGAH | 3912 | 6642 | 1476 | 4567 | 91 | 209 | 12985 |
14 | DI YOGYAKARTA | 537 | 1559 | 432 | 1363 | 23 | 177 | 3554 |
15 | JAWA TIMUR | 5437 | 6541 | 1975 | 5323 | 54 | 365 | 14258 |
16 | BANTEN | 658 | 2119 | 578 | 1475 | 42 | 91 | 4305 |
17 | BALI | 451 | 1584 | 513 | 1317 | 48 | 36 | 3498 |
18 | NUSA TENGGARA BARAT | 314 | 874 | 165 | 394 | 6 | 18 | 1457 |
19 | NUSA TENGGARA TIMUR | 449 | 602 | 139 | 139 | 1 | 1 | 882 |
20 | KALIMANTAN BARAT | 358 | 699 | 137 | 285 | 2 | 15 | 1138 |
21 | KALIMANTAN TENGAH | 267 | 546 | 103 | 227 | 0 | 10 | 886 |
22 | KALIMANTAN SELATAN | 389 | 820 | 241 | 489 | 2 | 31 | 1583 |
23 | KALIMANTAN TIMUR | 290 | 887 | 262 | 482 | 6 | 36 | 1673 |
24 | KALIMANTAN UTARA | 87 | 255 | 46 | 104 | 1 | 5 | 411 |
25 | SULAWESI UTARA | 281 | 961 | 134 | 516 | 13 | 8 | 1632 |
26 | SULAWESI TENGAH | 275 | 507 | 139 | 254 | 0 | 4 | 904 |
27 | SULAWESI SELATAN | 1009 | 1484 | 695 | 1146 | 10 | 84 | 3419 |
28 | SULAWESI TENGGARA | 356 | 571 | 180 | 211 | 3 | 4 | 969 |
29 | GORONTALO | 158 | 278 | 66 | 143 | 0 | 3 | 490 |
30 | SULAWESI BARAT | 150 | 229 | 91 | 86 | 1 | 7 | 414 |
31 | MALUKU | 259 | 314 | 53 | 95 | 6 | 3 | 471 |
32 | MALUKU UTARA | 180 | 245 | 48 | 91 | 2 | 4 | 390 |
33 | PAPUA BARAT | 207 | 222 | 40 | 93 | 3 | 1 | 359 |
34 | PAPUA | 422 | 585 | 78 | 139 | 0 | 2 | 804 |
Total | Total | 28754 | 53510 | 14211 | 35851 | 1087 | 2348 | 107007 |
Ternyata didapati colnames(data)
kurang tepat dan isi baris pertama
sebenarnya tidak diperlukan. Oke, sekarang kita akan membersihkan data
di atas dengan prinsip tidy
.
judul_kolom
dari data sebenarnya adalah isi baris (minus kolom kelima) ditambahcolnames(data)
element ke-9.
baris_1 = t(data[1,])
judul_kolom = c(baris_1[-5],colnames(data)[9])
- Ganti
colnames(data)
denganjudul_kolom
lalu hapus data baris pertama.
colnames(data) = judul_kolom
data = data[-1,]
- Hapus baris berisi
total
.
data =
data %>%
filter(No. != "Total")
Mari kita lihat hasilnya:
No. | Nama Provinsi | Jumlah Unit | Dokter Umum | Dokter Gigi | Dokter Spesialis | Dokter Sub Spesialis | Dokter Gigi Spesialis & Dokter Gigi Sub Spesialis | Jumlah (Per Provinsi) |
---|---|---|---|---|---|---|---|---|
1 | ACEH | 447 | 1556 | 375 | 806 | 16 | 22 | 2775 |
2 | SUMATERA UTARA | 827 | 3097 | 768 | 1817 | 59 | 51 | 5792 |
3 | SUMATERA BARAT | 426 | 1279 | 446 | 838 | 14 | 20 | 2597 |
4 | RIAU | 402 | 1452 | 428 | 622 | 23 | 15 | 2540 |
5 | JAMBI | 615 | 892 | 234 | 382 | 5 | 21 | 1534 |
6 | SUMATERA SELATAN | 463 | 1239 | 280 | 792 | 48 | 34 | 2393 |
7 | BENGKULU | 332 | 454 | 134 | 208 | 0 | 7 | 803 |
8 | LAMPUNG | 493 | 1346 | 197 | 691 | 7 | 15 | 2256 |
9 | KEPULAUAN BANGKA BELITUNG | 280 | 532 | 105 | 202 | 2 | 13 | 854 |
10 | KEPULAUAN RIAU | 185 | 620 | 162 | 361 | 5 | 27 | 1175 |
11 | DKI JAKARTA | 3193 | 6602 | 1972 | 6620 | 545 | 781 | 16520 |
12 | JAWA BARAT | 4645 | 5917 | 1519 | 3573 | 49 | 228 | 11286 |
13 | JAWA TENGAH | 3912 | 6642 | 1476 | 4567 | 91 | 209 | 12985 |
14 | DI YOGYAKARTA | 537 | 1559 | 432 | 1363 | 23 | 177 | 3554 |
15 | JAWA TIMUR | 5437 | 6541 | 1975 | 5323 | 54 | 365 | 14258 |
16 | BANTEN | 658 | 2119 | 578 | 1475 | 42 | 91 | 4305 |
17 | BALI | 451 | 1584 | 513 | 1317 | 48 | 36 | 3498 |
18 | NUSA TENGGARA BARAT | 314 | 874 | 165 | 394 | 6 | 18 | 1457 |
19 | NUSA TENGGARA TIMUR | 449 | 602 | 139 | 139 | 1 | 1 | 882 |
20 | KALIMANTAN BARAT | 358 | 699 | 137 | 285 | 2 | 15 | 1138 |
21 | KALIMANTAN TENGAH | 267 | 546 | 103 | 227 | 0 | 10 | 886 |
22 | KALIMANTAN SELATAN | 389 | 820 | 241 | 489 | 2 | 31 | 1583 |
23 | KALIMANTAN TIMUR | 290 | 887 | 262 | 482 | 6 | 36 | 1673 |
24 | KALIMANTAN UTARA | 87 | 255 | 46 | 104 | 1 | 5 | 411 |
25 | SULAWESI UTARA | 281 | 961 | 134 | 516 | 13 | 8 | 1632 |
26 | SULAWESI TENGAH | 275 | 507 | 139 | 254 | 0 | 4 | 904 |
27 | SULAWESI SELATAN | 1009 | 1484 | 695 | 1146 | 10 | 84 | 3419 |
28 | SULAWESI TENGGARA | 356 | 571 | 180 | 211 | 3 | 4 | 969 |
29 | GORONTALO | 158 | 278 | 66 | 143 | 0 | 3 | 490 |
30 | SULAWESI BARAT | 150 | 229 | 91 | 86 | 1 | 7 | 414 |
31 | MALUKU | 259 | 314 | 53 | 95 | 6 | 3 | 471 |
32 | MALUKU UTARA | 180 | 245 | 48 | 91 | 2 | 4 | 390 |
33 | PAPUA BARAT | 207 | 222 | 40 | 93 | 3 | 1 | 359 |
34 | PAPUA | 422 | 585 | 78 | 139 | 0 | 2 | 804 |
Apakah sudah selesai? Mari kita lihat kembali struktur data
kembali:
str(data)
## 'data.frame': 34 obs. of 9 variables:
## $ No. : chr "1" "2" "3" "4" ...
## $ Nama Provinsi : chr "ACEH" "SUMATERA UTARA" "SUMATERA BARAT" "RIAU" ...
## $ Jumlah Unit : chr "447" "827" "426" "402" ...
## $ Dokter Umum : chr "1556" "3097" "1279" "1452" ...
## $ Dokter Gigi : chr "375" "768" "446" "428" ...
## $ Dokter Spesialis : chr "806" "1817" "838" "622" ...
## $ Dokter Sub Spesialis : chr "16" "59" "14" "23" ...
## $ Dokter Gigi Spesialis & Dokter Gigi Sub Spesialis: chr "22" "51" "20" "15" ...
## $ Jumlah (Per Provinsi) : chr "2775" "5792" "2597" "2540" ...
Ternyata, variabel-variabel penting malah memiliki tipe character
bukan numeric
. Jadi langkah final kita tinggal mengkonversi
variabel-variabel tersebut menjadi numeric
. Ada banyak cara untuk bisa
melakukannya, tapi saya akan gunakan cara simpel dengan flow sebagai
berikut:
prov = data$`Nama Provinsi`
data =
data %>%
select(-`Nama Provinsi`) %>%
mutate_all(as.numeric)
data$`Nama Provinsi` = prov
Kita lihat kembali hasil finalnya:
## 'data.frame': 34 obs. of 9 variables:
## $ No. : num 1 2 3 4 5 6 7 8 9 10 ...
## $ Jumlah Unit : num 447 827 426 402 615 463 332 493 280 185 ...
## $ Dokter Umum : num 1556 3097 1279 1452 892 ...
## $ Dokter Gigi : num 375 768 446 428 234 280 134 197 105 162 ...
## $ Dokter Spesialis : num 806 1817 838 622 382 ...
## $ Dokter Sub Spesialis : num 16 59 14 23 5 48 0 7 2 5 ...
## $ Dokter Gigi Spesialis & Dokter Gigi Sub Spesialis: num 22 51 20 15 21 34 7 15 13 27 ...
## $ Jumlah (Per Provinsi) : num 2775 5792 2597 2540 1534 ...
## $ Nama Provinsi : chr "ACEH" "SUMATERA UTARA" "SUMATERA BARAT" "RIAU" ...
No. | Jumlah Unit | Dokter Umum | Dokter Gigi | Dokter Spesialis | Dokter Sub Spesialis | Dokter Gigi Spesialis & Dokter Gigi Sub Spesialis | Jumlah (Per Provinsi) | Nama Provinsi |
---|---|---|---|---|---|---|---|---|
1 | 447 | 1556 | 375 | 806 | 16 | 22 | 2775 | ACEH |
2 | 827 | 3097 | 768 | 1817 | 59 | 51 | 5792 | SUMATERA UTARA |
3 | 426 | 1279 | 446 | 838 | 14 | 20 | 2597 | SUMATERA BARAT |
4 | 402 | 1452 | 428 | 622 | 23 | 15 | 2540 | RIAU |
5 | 615 | 892 | 234 | 382 | 5 | 21 | 1534 | JAMBI |
6 | 463 | 1239 | 280 | 792 | 48 | 34 | 2393 | SUMATERA SELATAN |
7 | 332 | 454 | 134 | 208 | 0 | 7 | 803 | BENGKULU |
8 | 493 | 1346 | 197 | 691 | 7 | 15 | 2256 | LAMPUNG |
9 | 280 | 532 | 105 | 202 | 2 | 13 | 854 | KEPULAUAN BANGKA BELITUNG |
10 | 185 | 620 | 162 | 361 | 5 | 27 | 1175 | KEPULAUAN RIAU |
11 | 3193 | 6602 | 1972 | 6620 | 545 | 781 | 16520 | DKI JAKARTA |
12 | 4645 | 5917 | 1519 | 3573 | 49 | 228 | 11286 | JAWA BARAT |
13 | 3912 | 6642 | 1476 | 4567 | 91 | 209 | 12985 | JAWA TENGAH |
14 | 537 | 1559 | 432 | 1363 | 23 | 177 | 3554 | DI YOGYAKARTA |
15 | 5437 | 6541 | 1975 | 5323 | 54 | 365 | 14258 | JAWA TIMUR |
16 | 658 | 2119 | 578 | 1475 | 42 | 91 | 4305 | BANTEN |
17 | 451 | 1584 | 513 | 1317 | 48 | 36 | 3498 | BALI |
18 | 314 | 874 | 165 | 394 | 6 | 18 | 1457 | NUSA TENGGARA BARAT |
19 | 449 | 602 | 139 | 139 | 1 | 1 | 882 | NUSA TENGGARA TIMUR |
20 | 358 | 699 | 137 | 285 | 2 | 15 | 1138 | KALIMANTAN BARAT |
21 | 267 | 546 | 103 | 227 | 0 | 10 | 886 | KALIMANTAN TENGAH |
22 | 389 | 820 | 241 | 489 | 2 | 31 | 1583 | KALIMANTAN SELATAN |
23 | 290 | 887 | 262 | 482 | 6 | 36 | 1673 | KALIMANTAN TIMUR |
24 | 87 | 255 | 46 | 104 | 1 | 5 | 411 | KALIMANTAN UTARA |
25 | 281 | 961 | 134 | 516 | 13 | 8 | 1632 | SULAWESI UTARA |
26 | 275 | 507 | 139 | 254 | 0 | 4 | 904 | SULAWESI TENGAH |
27 | 1009 | 1484 | 695 | 1146 | 10 | 84 | 3419 | SULAWESI SELATAN |
28 | 356 | 571 | 180 | 211 | 3 | 4 | 969 | SULAWESI TENGGARA |
29 | 158 | 278 | 66 | 143 | 0 | 3 | 490 | GORONTALO |
30 | 150 | 229 | 91 | 86 | 1 | 7 | 414 | SULAWESI BARAT |
31 | 259 | 314 | 53 | 95 | 6 | 3 | 471 | MALUKU |
32 | 180 | 245 | 48 | 91 | 2 | 4 | 390 | MALUKU UTARA |
33 | 207 | 222 | 40 | 93 | 3 | 1 | 359 | PAPUA BARAT |
34 | 422 | 585 | 78 | 139 | 0 | 2 | 804 | PAPUA |
Bagaimana?
Mungkin ada kesan bahwa cara ini rumit yah dibandingkan save file Ms. Excel langsung dari website. Tapi kalau kalian ingin scrape semua detail kabupaten kota, cara ini jauh lebih cepat dibandingkan save manual satu-persatu lalu menggabungkannya di Ms. Excel.
Nantikan posting saya selanjutnya mengenai tutorial scrape data tenaga kesehatan (dokter) per kabupaten kota menggunakan R.