Visualisasi Data dengan Matplotlib

Selain statistik, visualisasi data juga memiliki peran penting dalam kegiatan analisis. Untuk keperluan tersebut, pada chapter ini kita akan belajar menggunakan module eksternal matplotlib untuk membuat berbagai macam visualisasi data.

Untuk melakukan instalasi module Matplotlib, buka program CMD.exe Prompt lewat Anaconda Navigator, lalu jalankan perintah di bawah ini:

conda install matplotlib

Setelah itu, jalankan aplikasi Spyder dari Anaconda Navigator dan tulis kode di bawah ini untuk melakukan impor module Matplotlib:

import matplotlib.pyplot as plt

Pada chapter ini, kita akan menggunakan data jumlah COVID-19 di negara-negara EU per hari tahun 2020-20221. Data dapat di akses melalui website resmi European Centre for Disease Prevention and Control.

Line plot

Diagram garis atau line plot adalah salah satu bentuk visualisasi untuk data yang memiliki tren atau berkaitan dengan waktu. Contoh berikut adalah kode untuk membuat visualisasi tren jumlah kasus COVID-19 per bulan pada tahun 2020 di negara Belgium dalam bentuk line plot:

# Contoh 1.1
import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('https://opendata.ecdc.europa.eu/covid19/nationalcasedeath_eueea_daily_ei/csv/data.csv', delimiter = ',')

# Step 1: filtering data
df_filtered = df[(df['countriesAndTerritories'] == 'Belgium') & (df['year'] == 2020)]

# Step 2: grouping 'month' dan aggregate
cases_bymonth = df_filtered.groupby(['month']).agg(cases = ('cases', 'sum')).reset_index()

# Step 3: inisialisasi plot
fig, ax = plt.subplots()
ax.plot(cases_bymonth['month'], cases_bymonth['cases'])

# Step 4: penambahan label x dan y axis
ax.set_xlabel('Month')
ax.set_ylabel('Cases')

# Step 5: penambahan judul plot
ax.set_title('Trend of COVID-19 cases in Belgium (2020)')

Ada beberapa step yang terlihat pada Contoh 1.1. Pembahasan per step adalah sebagai berikut:

  • Step 1: Kita membatasi visualisasi hanya untuk negara Belgium dan tahun 2020 saja. Sehingga pada step ini, kita melakukan filtering terhadap data aslinya.
  • Step 2: Karena data kasus COVID-19 masih dalam format per hari, maka kita perlu menjumlahkan tiap kasus per hari (agg sum) pada tiap bulan (groupby month).
  • Step 3: Inisialisasi plot. Fungsi plot menerima parameter pertama berupa list pada x axis, dan parameter kedua berupa list pada y axis.
  • Step 4: Penambahan label untuk x axis dan y axis.
  • Step 5: Penambahan judul plot dapat menggunakan fungsi set_title.

Plot yang dihasilkan dari Contoh 1.1 akan terlihat seperti gambar di bawah ini:

Line plot jumlah kasus COVID-19 per bulan pada tahun 2020 di negara Belgia

Apabila diperhatikan, angka ‘Month’ pada x axis tidak dimunculkan semua pada plot. Kita bisa memodifikasi kode pada Contoh 1.1 untuk menampilkan semua angka ‘Month’ pada x axis menjadi seperti contoh berikut:

# Contoh 1.2
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker # penambahan impor module `matplotlib.ticker`
import pandas as pd

df = pd.read_csv('https://opendata.ecdc.europa.eu/covid19/nationalcasedeath_eueea_daily_ei/csv/data.csv', delimiter = ',')

df_filtered = df[(df['countriesAndTerritories'] == 'Belgium') & (df['year'] == 2020)]
cases_bymonth = df_filtered.groupby(['month']).agg(cases = ('cases', 'sum')).reset_index()

fig, ax = plt.subplots()
ax.plot(cases_bymonth['month'], cases_bymonth['cases'])

ax.set_xlabel('Month')
ax.set_ylabel('Cases')
ax.set_title('Trend of COVID-19 cases in Belgium (2020)')

# Penambahan FixedLocator dengan parameter list yang sama dengan parameter x axis pada inisiasi plot
ax.xaxis.set_major_locator(ticker.FixedLocator(cases_bymonth['month']))

Plot yang dihasilkan dari Contoh 1.2 akan terlihat seperti gambar di bawah ini:

Line plot jumlah kasus COVID-19 per bulan pada tahun 2020 di negara Belgia (added ticker)

Scatter plot 2D

Scatter plot biasanya digunakan untuk memvisualisasikan hubungan antar variable pada data. Berbeda dengan line plot, visualisasi data pada scatter plot sifatnya lebih general, tidak selalu berorientasi terhadap waktu.

Masih menggunakan data COVID-19, Contoh 2.1 memperlihatkan pembuatan scatter plot 2 dimensi. Perbedaan dengan sebelumnya, scatter plot pada Matplotlib diinisialisasi menggunakan fungsi scatter.

# Contoh 2.1
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import pandas as pd

df = pd.read_csv('https://opendata.ecdc.europa.eu/covid19/nationalcasedeath_eueea_daily_ei/csv/data.csv', delimiter = ',')

df_filtered = df[(df['countriesAndTerritories'] == 'Belgium') & (df['year'] == 2020)]
cases_bymonth = df_filtered.groupby(['month']).agg(cases = ('cases', 'sum')).reset_index()

fig, ax = plt.subplots()
# Inisialisasi scatter plot
ax.scatter(cases_bymonth['month'], cases_bymonth['cases'])

ax.set_xlabel('Month')
ax.set_ylabel('Cases')
ax.set_title('Trend of COVID-19 cases in Belgium (2020)')
ax.xaxis.set_major_locator(ticker.FixedLocator(cases_bymonth['month']))

Plot yang dihasilkan Contoh 2.1 akan terlihat seperti gambar di bawah ini:

Scatter plot jumlah kasus COVID-19 per bulan pada tahun 2020 di negara Belgia

Bar plot

Seperti halnya scatter plot, Bar plot juga digunakan untuk memvisualisasikan hubungan antar variable. Bedanya, pada bar plot visualisasi dibuat menjadi bentuk balok-balok. Contoh di bawah ini memperlihatkan cara membuat bar plot dengan menggunakan fungsi bar:

# Contoh 3.1
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import pandas as pd

df = pd.read_csv('https://opendata.ecdc.europa.eu/covid19/nationalcasedeath_eueea_daily_ei/csv/data.csv', delimiter = ',')

df_filtered = df[(df['countriesAndTerritories'] == 'Belgium') & (df['year'] == 2020)]
cases_bymonth = df_filtered.groupby(['month']).agg(cases = ('cases', 'sum')).reset_index()

fig, ax = plt.subplots()
# Inisialisasi bar plot
ax.bar(cases_bymonth['month'], cases_bymonth['cases'])

ax.set_xlabel('Month')
ax.set_ylabel('Cases')
ax.set_title('Trend of COVID-19 cases in Belgium (2020)')
ax.xaxis.set_major_locator(ticker.FixedLocator(cases_bymonth['month']))

Plot yang dihasilkan Contoh 3.1 akan terlihat seperti gambar di bawah ini:

Bar plot jumlah kasus COVID-19 per bulan pada tahun 2020 di negara Belgia

Histogram

Histogram adalah salah satu bentuk visualisasi yang sering digunakan untuk menggambarkan distribusi dari suatu data. Kode berikut memperlihatkan cara membuat visualisasi histogram dari data COVID-19.

# Contoh 4.1
import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('https://opendata.ecdc.europa.eu/covid19/nationalcasedeath_eueea_daily_ei/csv/data.csv', delimiter = ',')
df_filtered = df[df['countriesAndTerritories'] == 'Belgium']

fig, ax = plt.subplots()
ax.hist(df_filtered['cases'])

Histogram yang dihasilkan Contoh 4.1 akan terlihat seperti gambar di bawah ini:

Histogram jumlah kasus COVID-19 di negara Belgia

Histogram di atas memperlihatkan distribusi yang skewed. Untuk melihat bentuk dari distribusi secara lebih detail, kita juga bisa melakukan pengaturan terhadap parameter bins. Perhatikan Contoh 4.1 dan hasil outputnya:

# Contoh 4.2
import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('https://opendata.ecdc.europa.eu/covid19/nationalcasedeath_eueea_daily_ei/csv/data.csv', delimiter = ',')
df_filtered = df[df['countriesAndTerritories'] == 'Belgium']

fig, ax = plt.subplots()
ax.hist(df_filtered['cases'], bins = 20)

Histogram jumlah kasus COVID-19 di negara Belgia (bins=20)

Selain itu, kita juga bisa melakukan kontrol terhadap batas tampilan histogram pada x dan y axis seperti Contoh 4.3:

# Contoh 4.3
import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('https://opendata.ecdc.europa.eu/covid19/nationalcasedeath_eueea_daily_ei/csv/data.csv', delimiter = ',')
df_filtered = df[df['countriesAndTerritories'] == 'Belgium']

fig, ax = plt.subplots()
ax.hist(df_filtered['cases'], bins = 30)

ax.set(xlim=(0, 20000), ylim=(0, 500))

Histogram jumlah kasus COVID-19 di negara Belgia (xlim dan ylim)

Box plot

Selain histogram, analisis distribusi data juga dapat dilakukan melalui visualisasi box plot.

# Contoh 5.1
import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('https://opendata.ecdc.europa.eu/covid19/nationalcasedeath_eueea_daily_ei/csv/data.csv', delimiter = ',')
df_filtered = df[df['countriesAndTerritories'].isin(['Luxembourg', 'Belgium', 'Netherlands'])]

fig, ax = plt.subplots()
ax.boxplot(df_filtered['cases'])

Box plot jumlah kasus COVID-19 di negara-negara Benelux

Pada output Contoh 5.1, terlalu banyak data outliers sehingga distribusinya kurang terlihat dengan jelas. Untuk memperbaiki visualisasi, kita juga bisa mengatur limit pada y axis seperti di bawah ini:

# Contoh 5.2
import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('https://opendata.ecdc.europa.eu/covid19/nationalcasedeath_eueea_daily_ei/csv/data.csv', delimiter = ',')
df_filtered = df[df['countriesAndTerritories'].isin(['Luxembourg', 'Belgium', 'Netherlands'])]

fig, ax = plt.subplots()
ax.boxplot(df_filtered['cases'])

ax.set(ylim=(0, 20000))

Box plot jumlah kasus COVID-19 di negara-negara Benelux (ylim)

Selain itu, kita juga bisa menampilkan boxplot per kategori (negara). Perhatikan contoh di bawah ini:

# Contoh 5.3
import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('https://opendata.ecdc.europa.eu/covid19/nationalcasedeath_eueea_daily_ei/csv/data.csv', delimiter = ',')
df_filtered = df[df['countriesAndTerritories'].isin(['Luxembourg', 'Belgium', 'Netherlands'])]

fig, ax = plt.subplots()
df_filtered.boxplot(column=['cases'], by='countriesAndTerritories', ax=ax)

ax.set(ylim=(0, 20000))

Box plot jumlah kasus COVID-19 di negara-negara Benelux (grouping)

Pada Contoh 5.3, kita melakukan pemanggilan fungsi boxplot dari object DataFrame, bukan dari object ax. Hal ini digunakan agar kita bisa mengontrol grouping boxplot melalui parameter by.

Membuat beberapa plot dalam satu diagram

Sebelumnya kita sudah sempat belajar membuat beberapa boxplot dalam satu diagram. Kita juga bisa menghasilkan hal yang serupa untuk tipe plot yang lain. Misalkan, kita bisa menampilkan beberapa line plot pada satu diagram seperti pada contoh berikut:

# Contoh 6.1
import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('https://opendata.ecdc.europa.eu/covid19/nationalcasedeath_eueea_daily_ei/csv/data.csv', delimiter = ',')
df_filtered = df[(df['countriesAndTerritories'].isin(['Luxembourg', 'Belgium', 'Netherlands'])) & (df['year'] == 2020)]
cases_bymonth = df_filtered.groupby(['countriesAndTerritories', 'month']).agg(cases = ('cases', 'sum')).reset_index()

df_lux = cases_bymonth[cases_bymonth['countriesAndTerritories'] == 'Luxembourg']
df_bel = cases_bymonth[cases_bymonth['countriesAndTerritories'] == 'Belgium']
df_nld = cases_bymonth[cases_bymonth['countriesAndTerritories'] == 'Netherlands']

fig, ax = plt.subplots()
ax.plot(df_lux['month'], df_lux['cases'], label = 'Luxembourg')
ax.plot(df_bel['month'], df_bel['cases'], label = 'Belgium')
ax.plot(df_nld['month'], df_nld['cases'], label = 'Netherlands')

ax.set_xlabel('Month')
ax.set_ylabel('Cases')
ax.set_title('Trend of COVID-19 cases in Belgium (2020)')
ax.legend()

Line plot jumlah kasus COVID-19 di negara-negara Benelux

Pada Contoh 6.1, kita melakukan filtering untuk memperoleh DataFrame per negara. Setelah mendapatkan DataFrame yang diinginkan, seperti biasa kita menggunakan fungsi plot untuk membuat visualisasi line plot. Bedanya, kita melakukan pemanggilan fungsi plot berkali-kali dengan DataFrame yang berbeda untuk tiap negara.

Tentu saja, kita juga bisa membuat visualisasi yang serupa untuk scatter plot dengan menggunakan fungsi scatter seperti contoh berikut:

# Contoh 6.2
import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('https://opendata.ecdc.europa.eu/covid19/nationalcasedeath_eueea_daily_ei/csv/data.csv', delimiter = ',')
df_filtered = df[(df['countriesAndTerritories'].isin(['Luxembourg', 'Belgium', 'Netherlands'])) & (df['year'] == 2020)]
cases_bymonth = df_filtered.groupby(['countriesAndTerritories', 'month']).agg(cases = ('cases', 'sum')).reset_index()

df_lux = cases_bymonth[cases_bymonth['countriesAndTerritories'] == 'Luxembourg']
df_bel = cases_bymonth[cases_bymonth['countriesAndTerritories'] == 'Belgium']
df_nld = cases_bymonth[cases_bymonth['countriesAndTerritories'] == 'Netherlands']

fig, ax = plt.subplots()
ax.(df_lux['month'], df_lux['cases'], label = 'Luxembourg')
ax.scatter(df_bel['month'], df_bel['cases'], label = 'Belgium')
ax.scatter(df_nld['month'], df_nld['cases'], label = 'Netherlands')

ax.set_xlabel('Month')
ax.set_ylabel('Cases')
ax.set_title('Trend of COVID-19 cases in Belgium (2020)')
ax.legend()

Scatter plot jumlah kasus COVID-19 di negara-negara Benelux

Apabila kita ingin membuat tiap plot menjadi diagram yang terpisah, kita bisa mengikuti contoh di bawah ini:

# Contoh 6.3
import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('https://opendata.ecdc.europa.eu/covid19/nationalcasedeath_eueea_daily_ei/csv/data.csv', delimiter = ',')
df_filtered = df[(df['countriesAndTerritories'].isin(['Luxembourg', 'Belgium', 'Netherlands'])) & (df['year'] == 2020)]

cases_bymonth = df_filtered.groupby(['countriesAndTerritories', 'month']).agg(cases = ('cases', 'sum')).reset_index()

# 1. Filter berdasarkan negara
df_lux = cases_bymonth[cases_bymonth['countriesAndTerritories'] == 'Luxembourg']
df_bel = cases_bymonth[cases_bymonth['countriesAndTerritories'] == 'Belgium']
df_nld = cases_bymonth[cases_bymonth['countriesAndTerritories'] == 'Netherlands']

# 2. Inisiasi plot dengan 3 baris
fig, axs = plt.subplots(nrows=3, sharex=True, sharey=True)

# 3. Membuat plot untuk tiap data negara + label
axs[0].plot(df_lux['month'], df_lux['cases'], label = 'Luxembourg')
axs[1].plot(df_bel['month'], df_bel['cases'], label = 'Belgium')
axs[2].plot(df_nld['month'], df_nld['cases'], label = 'Netherlands')

# 4. Setup label x dan y axis + legend
for ax in axs.flat:
    ax.set_xlabel('Month')
    ax.set_ylabel('Cases')
    ax.label_outer()
    ax.legend()

# 5. Set title
fig.suptitle('Trend of COVID-19 cases in Belgium (2020)')

Ada beberapa hal yang perlu diperhatikan pada Contoh 6.3:

  1. Setelah melakukan agregasi, kita perlu memisahkan DataFrame berdasarkan negara. Pada contoh, setiap negara dibuatkan variable DataFrame-nya sendiri, sehingga menghasilkan 3 variable baru.
  2. Pemanggilan fungsi subplots perlu ditambahkan parameter, yaitu nrows=3 untuk menentukan berapa baris plot yang kita inginkan, lalu sharex=True dan sharey=True untuk mengeset skala axis agar seragam untuk semua plot.
  3. Setelah inisiasi, variable axs akan berubah menjadi list. Kita bisa mengeset plot dengan semua variable DataFrame yang sudah kita buat sebelumnya pada list tersebut. Parameter label dibutuhkan untuk membedakan antara plot yang satu dengan plot yang lainnya (dalam hal ini kita beri nama sesuai dengan negaranya).
  4. Karena fungsi set_xlabel dan set_ylabel akan menggunakan label yang sama untuk semua plot (berulang), di sini kita gunakan looping. Fungsi label_outer digunakan untuk membuat label x dan y axis akan tampil hanya satu kali saja, sedangkan fungsi legend digunakan untuk menampilkan legenda pada plot.
  5. Untuk menambahkan judul untuk kumpulan plot, kita dapat menggunakan fungsi suptitle pada objek fig.

Hasil akhirnya dapat dilihat pada gambar di bawah ini:

Line plot jumlah kasus COVID-19 di negara-negara Benelux

Footnotes

  1. European Centre for Disease Prevention and Control. Data on the daily number of new reported COVID-19 cases and deaths by EU/EEA country (link to website)