Melakukan Visualisasi Data Kasus COVID19 di Indonesia

Kali ini kita akan coba untuk praktek visualisasi data menggunakan Python. Pada praktek kali ini saya akan menggunakan data kasus Covid19 di Indonesia. Saya mengambil data ini, karena topik mengenai Covid19 ini sendiri masih hangat dan data rujukannya mudah didapatkan.

Dari data yang nanti diambil, saya akan coba untuk visualisasikan kasus Covid19 tersebut pada setiap wilayah provinsi di Indonesia.

Data yang saya jadikan rujukan dalam tulisan kali ini bersumber dari website BNPB (https://bnpb-inacovid19.hub.arcgis.com/). Data yang disediakan dalam website tersebut sangat lengkap, bahkan datasetnya mengandung data geospatial yang nantinya data geospatial tersebut akan digunakan untuk melakukan plotting pada peta.

Dari berbagai macam dataset yang disediakan oleh website tersebut, saya memilih Data Harian Kasus per Provinsi COVID-19 Indonesia yang ada dalam tautan berikut https://bnpb-inacovid19.hub.arcgis.com/datasets/data-harian-kasus-per-provinsi-covid-19-indonesia/geoservice.

Proses pengambilan data menggunakan API yang memang disediakan oleh website tersebut. Data yang dihasilkan dari pemanggilan API tersebut dikembalikan dalam bentuk/ format JSON atau Java Script Object Notation.

Apa itu API?

API atau Application Programming Interface adalah sebuah antarmuka atau perantara antara sebuah aplikasi dengan aplikasi lainnya. Artinya saat kita membutuhkan sebuah data/informasi dari sebuah aplikasi lain kita tidak langsung mengakses pada sumber datanya, melainkan kita berkomunikasi dengan API dan API tersebut yang nantinya mengambilkan datanya untuk kita.

Ilustrasi sederhananya adalah seperti saat kita sedang membeli suatu obat di apotek. Saat kita akan membeli obat-obatan yang kita butuhkan, maka kita menyampaikannya pada apoteker. Apoteker tersebutlah yang akan mengambilkan obat-obat apa saja yang kita minta pada lemari obat-obatan yang ada. Setelah apoteker tersebut mendapatkan seluruh obat yang kita minta, maka obat tersebut akan diserahkan pada kita. Nah disini yang di ilustrasikan sebagai API adalah apoteker.

Apa itu JSON?

JSON atau yang memiliki kepanjangan JavaScript Object Notation adalah sebuah format data semi terstruktur yang umumnya digunakan untuk pertukaran dan penyimpanan data pada sebuah aplikasi.

Sebuah obyek JSON memiliki struktur seperti sebuah tipe data dictionary pada Python, yaitu memiliki pasangan key dan value-nya. Sebagai contoh, apabila kita memiliki sebuah data seperti ini:

Nama: Fani Widodo
Jenis Kelamin: Laki-laki
Alamat: Bandung
Tinggi Badan: 165

Maka apabila diimplementasikan dalam format JSON hasilnya seperti ini:

{
  “Nama”: “Fani Widodo”,
  “Jenis Kelamin”: “Laki-laki”,
  “Alamat”: “Bandung”,
  “Tinggi Badan”: 165
}

Apabila masih kurang jelas mengenai API ataupun JSON, silahkan bisa cari artikel-artikel di internet yang mengulas mengenai hal tersebut.

Format Dataset

Sebelum kita mempraktekkan cara melakukan plotting peta kasus Covid19. Maka kita perlu untuk memahami dataset yang dihasilkan oleh website BNPB tersebut. Pada dokumentasi yang disediakan sudah sangat jelas struktur dataset yang akan dihasilkan oleh API tersebut.

Pada tab Overview, kita bisa mendapatkan gambaran umum dataset yang dihasilkan beserta atribut datanya, bisa dilihat pada gambar dibawah ini.

Selanjutnya pada tab Data, kita bisa melihat dataset yang akan dihasilkan oleh API.

Terakhir pada tab API Explorer, kita bisa mengatur dataset apa saja yang nantinya akan dikembalikan oleh API tersebut. Contohnya pada bagian query kita bisa memasukkan filter datanya pada bagian where, selanjutnya kita juga bisa memilih kolom-kolom apa saja yang kita butuhkan dengan melakukan check atau uncheck di bagian Out Fields.

Pada praktik kali ini kita akan coba dengan setting default yang disediakan oleh API, tetapi apabila ingin melakukan eksperimen dengan merubah settingan pada API tersebut juga dipersilahkan.

Setelah dirasa semua settingan sudah sesuai coba tekan tombol Get Response untuk melihat hasil data (JSON) yang dihasilkan oleh API.

Dari informasi yang ada dalam website tersebut, berikut ini adalah penjelasan dari dataset yang dihasilkan.

  1. attributes
    • FID: ID Unik
    • Kode_Provi: Kode Provinsi
    • Provinsi: Nama Provinsi
    • Kasus_Posi: Jumlah Kasus Positiv Covid19
    • Kasus_Semb: Jumlah Kasus Sembuh Covid19
    • Kasus_Meni: Jumlah Kasus Meninggal Covid19
  2. geometry
    • x: Latitude
    • y: Longitude

Yang kita butuhkan untuk praktik kali ini adalah pada bagian Query URL, silahkan copy dan simpan data tersebut.

Mari Mulai Praktek

Import Library

Langkah pertama untuk melakukan visualisasi adalah kita akan memanggil semua library-library yang akan digunakan.

import requests
import json
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

Selanjutnya adalah memanggil API untuk pengambilan data.

response = requests.get('https://services5.arcgis.com/VS6HdKS0VfIhv8Ct/arcgis/rest/services/COVID19_Indonesia_per_Provinsi/FeatureServer/0/query?where=1%3D1&outFields=*&outSR=4326&f=json')
todos = json.loads(response.text)

Setelah API berhasil dipanggil, mari kita coba cetak hasil datanya menggunakan fungsi berikut ini agar hasilnya menjadi rapi.

def jsonprint(obj):
  # create a formatted string of the Python JSON object
  text = json.dumps(obj, indent=4)
  print(text)

jsonprint(response.json())

Dari pemanggilan fungsi tersebut, maka akan menghasilkan output seperti berikut ini. Banyak sekali data hasil dari pemanggilan API ini, tetapi kita hanya harus fokuskan pada hasil/ data utama saja. Apabila kita lihat, data utama berada pada bagian key “features” dimana didalamnya terdapat “attributes” dan “geometry“. Dari atribut tersebut maka kita bisa mengambil data-data utama seperti FID, Kode_Provi, Provinsi, Kasus_Posi, Kasus_Semb, Kasus_Meni, x, dan y.

{
    "objectIdFieldName": "FID",
    "uniqueIdField": {
        "name": "FID",
        "isSystemMaintained": true
    },
    "globalIdFieldName": "",
    "geometryType": "esriGeometryPoint",
    "spatialReference": {
        "wkid": 4326,
        "latestWkid": 4326
    },
    "fields": [
        {
            "name": "FID",
            "type": "esriFieldTypeOID",
            "alias": "FID",
            "sqlType": "sqlTypeOther",
            "domain": null,
            "defaultValue": null
        },
        {
            "name": "Kode_Provi",
            "type": "esriFieldTypeInteger",
            "alias": "Kode_Provi",
            "sqlType": "sqlTypeOther",
            "domain": null,
            "defaultValue": null
        },
        {
            "name": "Provinsi",
            "type": "esriFieldTypeString",
            "alias": "Provinsi",
            "sqlType": "sqlTypeOther",
            "length": 254,
            "domain": null,
            "defaultValue": null
        },
        {
            "name": "Kasus_Posi",
            "type": "esriFieldTypeInteger",
            "alias": "Kasus_Posi",
            "sqlType": "sqlTypeOther",
            "domain": null,
            "defaultValue": null
        },
        {
            "name": "Kasus_Semb",
            "type": "esriFieldTypeInteger",
            "alias": "Kasus_Semb",
            "sqlType": "sqlTypeOther",
            "domain": null,
            "defaultValue": null
        },
        {
            "name": "Kasus_Meni",
            "type": "esriFieldTypeInteger",
            "alias": "Kasus_Meni",
            "sqlType": "sqlTypeOther",
            "domain": null,
            "defaultValue": null
        }
    ],
    "features": [
        {
            "attributes": {
                "FID": 1,
                "Kode_Provi": 11,
                "Provinsi": "Aceh",
                "Kasus_Posi": 9616,
                "Kasus_Semb": 7898,
                "Kasus_Meni": 387
            },
            "geometry": {
                "x": 96.90952274776174,
                "y": 4.225081892093782
            }
        },
        {
            "attributes": {
                "FID": 2,
                "Kode_Provi": 12,
                "Provinsi": "Sumatera Utara",
                "Kasus_Posi": 25423,
                "Kasus_Semb": 22062,
                "Kasus_Meni": 859
            },
            "geometry": {
                "x": 99.05788784892918,
                "y": 2.1847792149105123
            }
        },
        {
            "attributes": {
                "FID": 3,
                "Kode_Provi": 13,
                "Provinsi": "Sumatera Barat",
                "Kasus_Posi": 29714,
                "Kasus_Semb": 28046,
                "Kasus_Meni": 655
            },
            "geometry": {
                "x": 100.46680503029916,
                "y": -0.8519143477257053
            }
        },
        {
            "attributes": {
                "FID": 4,
                "Kode_Provi": 14,
                "Provinsi": "Riau",
                "Kasus_Posi": 32103,
                "Kasus_Semb": 30337,
                "Kasus_Meni": 783
            },
            "geometry": {
                "x": 101.81289195391142,
                "y": 0.5105258491811052
            }
        },
        {
            "attributes": {
                "FID": 5,
                "Kode_Provi": 15,
                "Provinsi": "Jambi",
                "Kasus_Posi": 5637,
                "Kasus_Semb": 4526,
                "Kasus_Meni": 86
            },
            "geometry": {
                "x": 103.59931999973588,
                "y": -1.6177499996423312
            }
        },
...

Ekstraksi Atribut

Setelah kita dapat memetakan atribut-atribut tersebut maka kita bisa mengambil data-data utama seperti FID, Kode_Provi, Provinsi, Kasus_Posi, Kasus_Semb, Kasus_Meni, x, dan y menggunakan kode seperti berikut. Kemudian hasilnya akan disimpan pada DataFrame hasil.

features = response.json()['features']
data = []
for i in features:
    row = []
    row.append(i['attributes']['FID'])
    row.append(i['attributes']['Kode_Provi'])
    row.append(i['attributes']['Provinsi'])
    row.append(i['attributes']['Kasus_Posi'])
    row.append(i['attributes']['Kasus_Semb'])
    row.append(i['attributes']['Kasus_Meni'])
    row.append(i['geometry']['x'])
    row.append(i['geometry']['y'])
    data.append(row)
hasil = pd.DataFrame(data, columns=['fid', 'kode_prov', 'nama_prov', 'positif', 'sembuh', 'meninggal', 'lat', 'long'])

Untuk melihat seperti apa data yang dihasilkan, kita dapat memanggil langsung variabel hasil tersebut.

hasil

Berikut ini adalah tampilannya.

Kita juga dapat melihat format data yang disimpan pada masing-masing kolom dengan menggunakan perintah info().

hasil.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 35 entries, 0 to 34
Data columns (total 8 columns):
 #   Column     Non-Null Count  Dtype  
---  ------     --------------  -----  
 0   fid        35 non-null     int64  
 1   kode_prov  35 non-null     int64  
 2   nama_prov  35 non-null     object 
 3   positif    35 non-null     int64  
 4   sembuh     35 non-null     int64  
 5   meninggal  35 non-null     int64  
 6   lat        35 non-null     float64
 7   long       35 non-null     float64
dtypes: float64(2), int64(5), object(1)
memory usage: 2.3+ KB

Visualisasi

Visualisasi dalam bentuk Grafik Garis

Setelah data tersebut terkumpul, kita akan coba untuk membuat grafik dari data diatas. Berikut ini adalah grafik jumlah kasus positif, sembuh dan meninggal pada setiap provinsi.

plt.figure(figsize=(25, 10))
plt.plot(hasil['nama_prov'][:34], hasil['positif'][:34], label='Positif')
plt.plot(hasil['nama_prov'][:34], hasil['sembuh'][:34], label='Sembuh')
plt.plot(hasil['nama_prov'][:34], hasil['meninggal'][:34], label='Meninggal')
plt.xticks(rotation=90)
plt.legend()
plt.show()

Menampilkan Distribusi Kasus Covid19

Berikut ini adalah plotting distribusi frekuensi data kasus positiv covid.

sns.displot(hasil, x='positif', element='step', height=5, aspect=5)
plt.show()

Visualisasi dalam bentuk Grafik Batang

Berikut ini adalah grafik batang jumlah kasus positif, sembuh dan meninggal pada setiap provinsi.

sns.catplot(x='nama_prov', y='positif', kind='bar', data=hasil[:34], height=5, aspect=3)
plt.xticks(rotation=90)
plt.show()

Visualisasi dalam bentuk Grafik Titik

Berikut ini adalah grafik jumlah kasus positif, sembuh dan meninggal pada setiap provinsi dalam bentuk titik (plot).

sns.catplot(x='nama_prov', y='positif', data=hasil[:34], height=4, aspect=4)
plt.xticks(rotation=90)
plt.show()

Visualisasi dalam bentuk Titik Lokasi Terjadinya

Selanjutnya kita akan coba plotting kasus positif covid berdasarkan lokasi/ provinsi kasus tersebut terjadi. Plotting lokasi ini dimungkinkan karena seperti dijelaskan pada pembahasan dataset di awal, dataset yang dihasilkan oleh API ini kita memiliki data koordinat lokasi setiap provinsi (geometry x dan y).

Dengan data dari geometry x dan y kita dapat menempatkan titik-titik pada setiap koordinat. Berikut adalah kodenya.

x = hasil['lat']
y = hasil['long']

fig, ax = plt.subplots(figsize=(25,10))
sc = plt.scatter(x, y, alpha=.8)
plt.title('Peta Sebaran Kasus COVID19 di Indonesia')
plt.xlabel('Garis Bujur')
plt.ylabel('Garis Lintang')
plt.show()

Dibawah ini adalah hasil plotting datanya.

Nah, dari hasil visualisasi tersebut sudah bisa sedikit terlihat titik-titik lokasi provinsi terjadinya kasus Covid19.

Tetapi gambar diatas masih belum cukup informatif kaitannya dengan kasus Covid19, karena kita hanya melakukan plotting titik-titik lokasi/ provinsi terjadinya kasus Covid19 dan tidak ada informasi lainnya.

Agar bisa lebih informatif mari kita lakukan 2 hal, pertama kita rubah ukuran titik-titik tersebut sesuai dengan banyaknya kasus Covid19 yang terjadi pad masing-masing provinsi. Semakin besar ukuran titik maka semakin banyak kasus Covid19 yang terjadi di provinsi tersebut. Demikian juga kebalikannya, semakin kecil titik maka semakin sedikit kasusnya.

Kemudian yang kedua, kita rubah warna masing-masing titik agar terlihat perbedaannya pada masing-masing provinsi. Untuk itu, silahkan ketik dan jalankan kode berikut.

x = hasil['lat']
y = hasil['long']
size = hasil['positif'] / 100
color = hasil['fid']

fig, ax = plt.subplots(figsize=(25,10))
sc = plt.scatter(x, y, s=size, c=color, alpha=.8)
plt.colorbar(sc, orientation="horizontal")
plt.title('Peta Sebaran Kasus COVID19 di Indonesia')
plt.xlabel('Garis Bujur')
plt.ylabel('Garis Lintang')
plt.xlim([96.90952274776174-2, 140.0000000003746+2])
plt.ylim([-8.606652084111358-2, 4.225081892093782+2])
plt.show()

Dari kode diatas apabila dijalankan maka akan menghasilkan gambar sebagai berikut.

Dari gambar diatas kita kini sudah bisa melihat dan membedakan di wilayah provinsi mana sajakah kasus Covid19 yang paling banyak atau paling sedikit terjadi.

Tetapi visualisasi diatas juga masih belum bisa dibilang informatif, karena kita tidak bisa melihat lokasi persisnya kasus Covid19 tersebut. Oleh karenanya, agar visualisasi bisa lebih informatif kepada orang lain, maka kita juga perlu untuk menggambar peta wilayah Indonesia.

Untuk melakukan hal tersebut, maka kita membutuhkan library lainnya untuk menggambar peta. Kali ini kita akan membutuhkan bantuan library geopandas.

Langkah pertama untuk menggunakan library ini tentunya kita harus menginstallnya, berikut adalah perintah instalasi library tersebut.

pip install geopandas
Collecting geopandas
Downloading https://files.pythonhosted.org/packages/d7/bf/e9cefb69d39155d122b6ddca53893b61535fa6ffdad70bf5ef708977f53f/geopandas-0.9.0-py2.py3-none-any.whl (994kB)
|████████████████████████████████| 1.0MB 4.9MB/s
Requirement already satisfied: shapely>=1.6 in /usr/local/lib/python3.7/dist-packages (from geopandas) (1.7.1)
Requirement already satisfied: pandas>=0.24.0 in /usr/local/lib/python3.7/dist-packages (from geopandas) (1.1.5)
Collecting fiona>=1.8
Downloading https://files.pythonhosted.org/packages/47/c2/67d1d0acbaaee3b03e5e22e3b96c33219cb5dd392531c9ff9cee7c2eb3e4/Fiona-1.8.18-cp37-cp37m-manylinux1_x86_64.whl (14.8MB)
|████████████████████████████████| 14.8MB 310kB/s
Collecting pyproj>=2.2.0
Downloading https://files.pythonhosted.org/packages/b1/72/d52e9ca81caef056062d71991b0e9b1d16af042245627c5d0e4916a36c4f/pyproj-3.0.1-cp37-cp37m-manylinux2010_x86_64.whl (6.5MB)
|████████████████████████████████| 6.5MB 39.6MB/s
Requirement already satisfied: python-dateutil>=2.7.3 in /usr/local/lib/python3.7/dist-packages (from pandas>=0.24.0->geopandas) (2.8.1)
Requirement already satisfied: numpy>=1.15.4 in /usr/local/lib/python3.7/dist-packages (from pandas>=0.24.0->geopandas) (1.19.5)
Requirement already satisfied: pytz>=2017.2 in /usr/local/lib/python3.7/dist-packages (from pandas>=0.24.0->geopandas) (2018.9)
Collecting click-plugins>=1.0
Downloading https://files.pythonhosted.org/packages/e9/da/824b92d9942f4e472702488857914bdd50f73021efea15b4cad9aca8ecef/click_plugins-1.1.1-py2.py3-none-any.whl
Requirement already satisfied: certifi in /usr/local/lib/python3.7/dist-packages (from fiona>=1.8->geopandas) (2020.12.5)
Requirement already satisfied: six>=1.7 in /usr/local/lib/python3.7/dist-packages (from fiona>=1.8->geopandas) (1.15.0)
Collecting cligj>=0.5
Downloading https://files.pythonhosted.org/packages/42/1e/947eadf10d6804bf276eb8a038bd5307996dceaaa41cfd21b7a15ec62f5d/cligj-0.7.1-py3-none-any.whl
Collecting munch
Downloading https://files.pythonhosted.org/packages/cc/ab/85d8da5c9a45e072301beb37ad7f833cd344e04c817d97e0cc75681d248f/munch-2.5.0-py2.py3-none-any.whl
Requirement already satisfied: attrs>=17 in /usr/local/lib/python3.7/dist-packages (from fiona>=1.8->geopandas) (20.3.0)
Requirement already satisfied: click<8,>=4.0 in /usr/local/lib/python3.7/dist-packages (from fiona>=1.8->geopandas) (7.1.2)
Installing collected packages: click-plugins, cligj, munch, fiona, pyproj, geopandas
Successfully installed click-plugins-1.1.1 cligj-0.7.1 fiona-1.8.18 geopandas-0.9.0 munch-2.5.0 pyproj-3.0.1

Setelah library geopandas terinstal, maka langkah selanjutnya adalah melakukan import pada library tersebut agar bisa kita gunakan.

import geopandas as gpd

Selanjutnya, kita juga membutuhkan dataset wilayah Indonesia agar dapat melakukan plotting peta. Data tersebut berupa file ber-ekstensi .shp dan .shx yang bisa kita cari melalui google. Tapi untuk memudahkan, file tersebut sudah saya sediakan dalam link GitHub saya disini.

Download terlebih dahulu 2 file tersebut, kemudian simpan dalam satu lokasi dengan kode yang telah kita buat.

Untuk menggunakan data peta wilayah Indonesia kita import dahulu file .shp dan .shx diperoleh dan simpan data tersebut dalam sebuah variabel. Kemudian dari data peta wilayah Indonesia tersebut kita lakukan plotting bersamaan dengan plotting titik-titik peta kasus positif covid di Indonesia. Untuk melakukan hal tersebut ketiklah kode dibawah ini.

map_df = gpd.read_file("Indonesia.shx")

kordinat = hasil[['lat', 'long']]
merged = map_df.join(kordinat)

x = hasil['lat']
y = hasil['long']
size = hasil['positif'] / 100
color = hasil['fid']

fig, ax = plt.subplots(figsize=(25,10))
ax = map_df.plot(figsize=(20,10), cmap='YlGn')
sc = plt.scatter(x, y, s=size, c=color, alpha=.5, cmap='hot')
plt.title('Peta Sebaran Kasus COVID19 di Indonesia')
plt.xlabel('Garis Bujur')
plt.ylabel('Garis Lintang')
plt.show()

Apabila tidak ada kesalahan dalam kode, maka akan tampil grafik seperti gambar dibawah ini.

Nah, kali ini visualisasi kasus Covid19 yang kita buat sudah cukup informatif kan? Dari visualisasi tersebut kita bisa melihat wilayah provinsi mana saja yang ada kasus covid, serta seberapa besar jumlah kasus Covid19 di wilayah tersebut.

 

Referensi:

  1. Data Covid19 di Indonesia – https://bnpb-inacovid19.hub.arcgis.com
  2. Geopandas – https://geopandas.org/
  3. https://github.com/jfanniw/Visualisasi-Kasus-COVID19-Indonesia

 

 

 

You may also like...