Proyek ini merupakan proyek yang terdapat pada DQLAB, dimana merupakan hasil eksplorasi sederhana terhadap data Covid-19 di Indonesia, Data yang digunakan diambil langsung dari API (Application Programming Interface) yang tersedia di covid19.go.id. Sehingga dalam proyek ini akan mempelajari terkait pengambilan data dari API hingga melakukan visualisasi data.
Rekapitulasi data COVID-19 Indonesia tersedia dalam API publik yang beralamat di ___https://data.covid19.go.id/public/api/update.json___. Salah satu cara untuk mengakses API adalah dengan menggunakan fungsi GET() dari paket httr.
Penulis menggunakan nama rsp sebagai tempat penyimpanan data COVID-19
library(httr)
resp <- GET("https://data.covid19.go.id/public/api/update.json")
status_code(resp)
## [1] 200
pada code sebelumnya ditulis status_code() yang artinya melihat apakah API yang kita akses sudah berhasil atau sebaliknya, dimana status kode nya itu sendiri memiliki beberapa kriteria seperti:
*** 200. Artinya permintaan sukses dipenuhi. *** 404. Artinya berkas yang diminta tidak dapat ditemukan. *** 403. Artinya akses permintaan ditolak. *** 500. Artinya terjadi kesalahan pada server.
Setelah permintaan API telah dipenuhi langkah selanjutnya mencoba menjalankan fungsi headers() pada resp untuk mengetahui metadata apa saja yang tersimpan. Apakah isi dari elemen content-type? Kapan terakhir kali informasi diperbaharui?
library(httr)
resp <- GET("https://data.covid19.go.id/public/api/update.json")
headers(resp)
## $server
## [1] "nginx"
##
## $date
## [1] "Sat, 22 Aug 2020 10:36:46 GMT"
##
## $`content-type`
## [1] "application/json"
##
## $`last-modified`
## [1] "Sat, 22 Aug 2020 10:34:56 GMT"
##
## $`transfer-encoding`
## [1] "chunked"
##
## $connection
## [1] "keep-alive"
##
## $vary
## [1] "Accept-Encoding"
##
## $etag
## [1] "W/\"5f40f4d0-1026c\""
##
## $`content-encoding`
## [1] "gzip"
##
## attr(,"class")
## [1] "insensitive" "list"
Respon API dengan status code 200 menyatakan bahwa permintaan Kita berhasil dipenuhi dan konten yang diminta tersedia untuk diekstrak. Selain itu Kita juga telah mengetahui lewat fungsi headers() bahwa konten yang diminta tersedia dalam bentuk application/json, yaitu berkas JSON.
Selanjutnya Penulis dapat mengekstrak konten tersebut dengan menggunakan fungsi content(). Fungsi content() tersebut secara cerdas akan menyesuaikan output sesuai dengan jenis berkas yang tersedia, dalam hal ini adalah berkas JSON. Penulis Menjalankan fungsi tersebut pada obyek resp dan menambahkan argumen as = "parsed" dan simplifyVector = TRUE yang disimpan sebagai cov_id_raw.
library(httr)
resp <- GET("https://data.covid19.go.id/public/api/update.json")
cov_id_raw <- content(resp, as = "parsed", simplifyVector = TRUE)
dengan mengamati menggunakan fungsi length() dan names() penulis mengamati ada berapa komponen serta apa saja nama komponen dalam obyek cov_id_raw tersebut! Kemudian ekstraklah komponen ke-2 dan menyimpan dengan nama cov_id_update
length(cov_id_raw)
## [1] 2
names(cov_id_raw)
## [1] "data" "update"
cov_id_update <- cov_id_raw$update
Sekarang Penulis diminta untuk fokus pada obyek cov_id_update untuk menjawab beberapa pertanyaan berikut:
*** Kapan tanggal pembaharuan data penambahan kasus? *** Berapa jumlah penambahan kasus sembuh? *** Berapa jumlah penambahan kasus meninggal? *** Berapa jumlah total kasus positif hingga saat ini? *** Berapa jumlah total kasus meninggal hingga saat ini?
penulis menggunakan fungsi lapply() untuk melihat names pada cov_id_update secara bersamaan
lapply(cov_id_update, names)
## $penambahan
## [1] "jumlah_positif" "jumlah_meninggal" "jumlah_sembuh" "jumlah_dirawat"
## [5] "tanggal" "created"
##
## $harian
## [1] "key_as_string" "key" "doc_count"
## [4] "jumlah_meninggal" "jumlah_sembuh" "jumlah_positif"
## [7] "jumlah_dirawat" "jumlah_positif_kum" "jumlah_sembuh_kum"
## [10] "jumlah_meninggal_kum" "jumlah_dirawat_kum"
##
## $total
## [1] "jumlah_positif" "jumlah_dirawat" "jumlah_sembuh" "jumlah_meninggal"
cov_id_update$penambahan$tanggal
## [1] "2020-08-22"
cov_id_update$penambahan$jumlah_sembuh
## [1] 2207
cov_id_update$penambahan$jumlah_meninggal
## [1] 94
cov_id_update$total$jumlah_positif
## [1] 151498
cov_id_update$total$jumlah_meninggal
## [1] 6594
dari hasil tersebut dapt diketahui bahwa penambhaan terbaru terjadi pada tanggal 18-08-2020 dengan update jumlah sebmbuh teraru sebanyak 1848, jumlah meninggal pada update terakhir sebanyak 70 orang, jumlah terupdate pasien positif sebanyak 143043 dan total jumlah meninggal sebanyak 6277 orang.
Penulis telah berhasil menjawab pertanyaan mengenai kondisi COVID-19 di Indonesia dengan menggunakan data yang langsung diambil menggunakan API. Namun bagaimana jika Penulis ingin berfokus dengan data COVID-19 di provinsi tempat menetap saat ini?
covid19.go.id menyediakan data kasus COVID-19 tingkat provinsi di alamat API yang berbeda. Sebagai contoh data mengenai COVID-19 Jawa Barat, tempat tinggal saya sekarang, tersedia di https://data.covid19.go.id/public/api/prov_detail_JAWA_BARAT.json dan dapat diakses menggunakan baris kode berikut:
library(httr)
resp_jabar <- GET("https://data.covid19.go.id/public/api/prov_detail_JAWA_BARAT.json")
cov_jabar_raw <- content(resp_jabar, as = "parsed", simplifyVector = TRUE)
dan menjawab pertanyaan yang sama dengan code sebagai berikut:
names(cov_jabar_raw)
## [1] "last_date" "provinsi" "kasus_total"
## [4] "kasus_tanpa_tgl" "kasus_dengan_tgl" "meninggal_persen"
## [7] "meninggal_tanpa_tgl" "meninggal_dengan_tgl" "sembuh_persen"
## [10] "sembuh_tanpa_tgl" "sembuh_dengan_tgl" "list_perkembangan"
## [13] "data"
cov_jabar_raw$kasus_total
## [1] 9081
cov_jabar_raw$meninggal_persen
## [1] 2.775025
cov_jabar_raw$sembuh_persen
## [1] 54.72966
informasi yang didaptkan oleh penulis sudah baik namun belum cukup lengkap untuk menjawab pertanyaan pertanyaan yang lebih spesifik lagi dari waktu kewaktu.
Kabar baiknya adalah informasi tersebut juga disediakan oleh covid19.go.id melalui permintaan API yang telah Penulis buat sebelumnya. Data historis perkembangan COVID-19 tersebut tersimpan dengan nama list_perkembangan. Ekstrak data tersebut dari cov_jabar_raw dan simpan hasilnya sebagai obyek bernama cov_jabar dan Amati struktur cov_jabar menggunakan fungsi str() dan head().
cov_jabar <- cov_jabar_raw$list_perkembangan
str(cov_jabar)
## 'data.frame': 174 obs. of 9 variables:
## $ tanggal : num 1.58e+12 1.58e+12 1.58e+12 1.58e+12 1.58e+12 ...
## $ KASUS : int 3 0 1 1 0 1 0 0 0 0 ...
## $ MENINGGAL : int 0 0 1 0 0 0 0 0 0 0 ...
## $ SEMBUH : int 0 0 0 0 0 0 0 0 0 0 ...
## $ DIRAWAT_OR_ISOLASI : int 3 0 0 1 0 1 0 0 0 0 ...
## $ AKUMULASI_KASUS : int 3 3 4 5 5 6 6 6 6 6 ...
## $ AKUMULASI_SEMBUH : int 0 0 0 0 0 0 0 0 0 0 ...
## $ AKUMULASI_MENINGGAL : int 0 0 1 1 1 1 1 1 1 1 ...
## $ AKUMULASI_DIRAWAT_OR_ISOLASI: int 3 3 3 4 4 5 5 5 5 5 ...
head(cov_jabar)
## tanggal KASUS MENINGGAL SEMBUH DIRAWAT_OR_ISOLASI AKUMULASI_KASUS
## 1 1.583021e+12 3 0 0 3 3
## 2 1.583107e+12 0 0 0 0 3
## 3 1.583194e+12 1 1 0 0 4
## 4 1.583280e+12 1 0 0 1 5
## 5 1.583366e+12 0 0 0 0 5
## 6 1.583453e+12 1 0 0 1 6
## AKUMULASI_SEMBUH AKUMULASI_MENINGGAL AKUMULASI_DIRAWAT_OR_ISOLASI
## 1 0 0 3
## 2 0 0 3
## 3 0 1 3
## 4 0 1 4
## 5 0 1 4
## 6 0 1 5
Setelah mengekstrak dan mengamati cov_jabar, Penulis menemukan beberapa kejanggalan pada data tersebut. Diantaranya adalah kejanggalan data pada kolom tanggal dan format penulisan kolom yang tidak konsisten. Sekarang Penulis akan mencoba melakukan beberapa tahapan untuk menjinakan data tersebut sehingga dapat diolah dan dianalisis dengan lebih mudah.
Sebelum itu, silakan aktifkan paket dplyr yang akan dipergunakan untuk melakukan pengolahan data.
Ada beberapa tahapan yang akan dilakukan untuk menjinakan data cov_jabar, yaitu:
Penulis akan menggunakan operator pipe (%>%) untuk merangkai fungsi menjadi sebuah pipeline. dan menyimpan hasil pengolahandengan nama new_cov_jabar.
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
new_cov_jabar <-
cov_jabar %>%
select(-contains("DIRAWAT_OR_ISOLASI")) %>%
select(-starts_with("AKUMULASI")) %>%
rename(
kasus_baru = KASUS,
meninggal = MENINGGAL,
sembuh = SEMBUH
) %>%
mutate(
tanggal = as.POSIXct(tanggal / 1000, origin = "1970-01-01"),
tanggal = as.Date(tanggal)
)
str(new_cov_jabar)
## 'data.frame': 174 obs. of 4 variables:
## $ tanggal : Date, format: "2020-03-01" "2020-03-02" ...
## $ kasus_baru: int 3 0 1 1 0 1 0 0 0 0 ...
## $ meninggal : int 0 0 1 0 0 0 0 0 0 0 ...
## $ sembuh : int 0 0 0 0 0 0 0 0 0 0 ...
Selanjutnya Penluis melakukan visusalisai yang sama namun menggunakan Kasus sembuh sebagai sumbu Y
library(ggplot2)
library(hrbrthemes)
ggplot(new_cov_jabar, aes(tanggal, sembuh)) +
geom_col(fill = "olivedrab2") +
labs(
x = NULL,
y = "Jumlah kasus",
title = "Kasus Harian Sembuh Dari COVID-19 di Jawa Barat",
caption = "Sumber data: covid.19.go.id"
) +
theme_ipsum(
base_size = 13,
plot_title_size = 21,
grid = "Y",
ticks = TRUE
) +
theme(plot.title.position = "plot")
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
Selanjutnya penulis akna melihat bagaimana perkembangan Covid pada Pekan ini atau pekan terbaru terakhir update data dengan mengekstrak waktu setiap pekannya yaitu week() yang dimana dapt mengetahui apakah pekan lalu lebih baik dari pada pekan sekarang atau sebaliknya.
library(dplyr)
library(lubridate)
##
## Attaching package: 'lubridate'
## The following object is masked from 'package:base':
##
## date
cov_jabar_pekanan <- new_cov_jabar %>%
count(
tahun = year(tanggal),
pekan_ke = week(tanggal),
wt = kasus_baru,
name = "jumlah"
)
glimpse(cov_jabar_pekanan)
## Rows: 26
## Columns: 3
## $ tahun <dbl> 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020...
## $ pekan_ke <dbl> 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,...
## $ jumlah <int> 4, 2, 18, 45, 129, 185, 217, 238, 227, 338, 243, 151, 427,...
untuk membuat grafik berwarna penulis dapat menambahkan fill = lebih_baik pada bar chart agar tampilan lebih menarik
library(ggplot2)
library(hrbrthemes)
ggplot(cov_jabar_pekanan, aes(pekan_ke, jumlah)) +
geom_col(show.legend = FALSE) +
scale_x_continuous(breaks = 9:29, expand = c(0, 0)) +
scale_fill_manual(values = c("TRUE" = "seagreen3", "FALSE" = "salmon")) +
labs(
x = NULL,
y = "Jumlah kasus",
title = "Kasus Pekanan Positif COVID-19 di Jawa Barat",
subtitle = "Kolom hijau menunjukan penambahan kasus baru lebih sedikit dibandingkan satu pekan sebelumnya",
caption = "Sumber data: covid.19.go.id"
) +
theme_ipsum(
base_size = 13,
plot_title_size = 21,
grid = "Y",
ticks = TRUE
) +
theme(plot.title.position = "plot")
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
selanjutnya jika penulis ingin melihat pola dinamika yang terjadi di data covid-19 dapat meggunakan kode berikut:
library(dplyr)
cov_jabar_akumulasi <-
new_cov_jabar %>%
transmute(
tanggal,
akumulasi_aktif = cumsum(kasus_baru) - cumsum(sembuh) - cumsum(meninggal),
akumulasi_sembuh = cumsum(sembuh),
akumulasi_meninggal = cumsum(meninggal)
)
tail(cov_jabar_akumulasi)
## tanggal akumulasi_aktif akumulasi_sembuh akumulasi_meninggal
## 169 2020-08-16 3685 4662 232
## 170 2020-08-17 3684 4707 233
## 171 2020-08-18 3713 4723 233
## 172 2020-08-19 3765 4771 237
## 173 2020-08-20 3893 4842 239
## 174 2020-08-21 3860 4965 247
penulis juga dapat menggunakan line chart unutk melihat bagaimana perkembangan dari waktu kewaktu
library(ggplot2)
ggplot(data = cov_jabar_akumulasi, aes(x = tanggal, y = akumulasi_aktif)) +
geom_line()
### Transformasi Data
akan menggunakan fungsi gather() dari paket tidyr untuk mentransformasi data cov_jabar_akumulasi. Data tersebut akan dirubah dari yang semula berformat wide menjadi format long. AKtifkanlah paket tidyr terlebih dahulu dan lengkapilah baris kode berikut untuk melakukan pivot data dan menyimpannya pada cov_jabar_akumulasi_pivot.
library(dplyr)
library(tidyr)
dim(cov_jabar_akumulasi)
## [1] 174 4
cov_jabar_akumulasi_pivot <-
cov_jabar_akumulasi %>%
gather(
key = "kategori",
value = "jumlah",
-tanggal
) %>%
mutate(
kategori = sub(pattern = "akumulasi_", replacement = "", kategori)
)
dim(cov_jabar_akumulasi_pivot)
## [1] 522 3
glimpse(cov_jabar_akumulasi_pivot)
## Rows: 522
## Columns: 3
## $ tanggal <date> 2020-03-01, 2020-03-02, 2020-03-03, 2020-03-04, 2020-03-0...
## $ kategori <chr> "aktif", "aktif", "aktif", "aktif", "aktif", "aktif", "akt...
## $ jumlah <int> 3, 3, 3, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 18, 21, 27...