Gramatika berlapis dalam praktik

Garis keturunan ggplot2 di Python melalui plotnine dan plotly express beserta perbedaan cara kerjanya.

Daftar isi

Gramatika grafis lahir sebagai buku teori, lalu menjadi kode yang dapat dijalankan ketika ggplot2 dibangun di atas bahasa R. Di Python, gagasan itu diteruskan oleh plotnine sebagai port ggplot2 dan oleh plotly express sebagai API bergaya gramatika yang mengembalikan figur web. Topik ini menjalankan kedua implementasi pada dataset yang sama, membandingkan cara kerjanya, dan menempatkan Vega-Lite sebagai spesifikasi deklaratif dalam keluarga yang sama.

ggplot2 di R dan plotnine di Python#

ggplot2 adalah implementasi gramatika grafis yang paling banyak digunakan dan tetap berjalan pada bahasa asalnya, yaitu R, dengan paket yang terdaftar di CRAN. plotnine menerapkan model yang sama di Python sambil mempertahankan bentuk ekspresinya, yaitu fungsi lapisan yang dirangkai dengan tanda tambah. Spesifikasi grafik tertulis sebagai ekspresi, data diteruskan ke fungsi ggplot, pemetaan dinyatakan melalui aes, lalu setiap lapisan tambahan dirangkai dengan tanda +. Demo berikut menggambar rata-rata nilai matematika per kelas langsung dari nilai_ujian.csv, dan agregasinya tidak dilakukan di luar grafik, tetapi dikerjakan oleh lapisan statistik melalui stat_summary, sehingga kalimat lapisannya lengkap sampai geometri batang.

python gramatika-plotnine.py
import pandas as pd
import numpy as np
from plotnine import aes, ggplot, labs, stat_summary

# lapisan data: tabel tidy dari dataset jalur
tabel = pd.read_csv("nilai_ujian.csv")

# lapisan statistik dikerjakan di dalam grafik: stat_summary menghitung
# rata-rata, lapisan geometri menggambarnya sebagai batang
grafik = (
    ggplot(tabel, aes(x="kelas", y="nilai_matematika", fill="kelas"))
    + stat_summary(fun_y=np.mean, geom="col")
    + labs(
        title="Rata-rata nilai matematika per kelas",
        x="Kelas",
        y="Rata-rata nilai matematika",
    )
)

grafik.save("gramatika-plotnine.svg", width=6, height=3.5, verbose=False)
print("berkas gramatika-plotnine.svg tersimpan")
text Keluaran
berkas gramatika-plotnine.svg tersimpan
Rata-rata nilai matematika per kelas yang digambar plotnine

Gambar di atas menunjukkan tiga lapisan berjalan sekaligus. stat_summary menghitung rata-rata per kelas sebagai lapisan statistik, geom_col menggambarkannya sebagai batang, dan pemetaan fill="kelas" memunculkan legenda tanpa perintah tambahan karena panduan dibuat otomatis dari pemetaan. Skrip hanya berisi kalimat gramatika, sedangkan keputusan pikselnya ditentukan oleh skala bawaan.

Kelengkapan gramatika inilah kekuatan utama plotnine. Lapisan statistik, skala, faset, dan panduan tersedia sebagai fungsi terpisah dengan argumen yang sama seperti ggplot2, sehingga bab dokumentasi ggplot2 tetap relevan ketika alatnya berganti bahasa. Biayanya ada pada keluaran, yaitu hasilnya berupa gambar statis matplotlib yang perlu disimpan sebagai berkas ketika ingin dipublikasikan.

Plotly express: gramatika yang menjadi JSON#

plotly express menawarkan kalimat gramatika yang sama dengan cara kerja yang berbeda. Fungsi px, misalnya px.bar, menerima tabel tidy beserta argumen pemetaan seperti x, y, dan color, lalu mengembalikan objek figur. Objek figur itu tersusun sebagai JSON, dengan daftar trace di bagian data dan penataan di bagian layout, sehingga figur siap dirender secara interaktif di browser. Perbedaan cara kerjanya terletak di sini, yaitu plotnine merender gambar statis melalui matplotlib, sedangkan plotly menyusun struktur web yang baru digambar ketika halamannya dibuka. Demo berikut membuat figur yang sama dengan demo plotnine dan menampilkan isi figurnya secara ringkas.

python gramatika-plotly.py
import pandas as pd
import plotly.express as px

# agregasi dilakukan terlebih dahulu dengan pandas
tabel = pd.read_csv("nilai_ujian.csv")
rata = tabel.groupby("kelas", as_index=False)["nilai_matematika"].mean().round(2)

# satu pemanggilan fungsi px mengembalikan objek figur berisi trace
fig = px.bar(rata, x="kelas", y="nilai_matematika", color="kelas")

print("jumlah trace:", len(fig.data))
for trace in fig.data:
    x = [str(v) for v in trace.x]
    y = [round(float(v), 2) for v in trace.y]
    print(f"type={trace.type} name={trace.name} x={x} y={y}")
text Keluaran
jumlah trace: 2
type=bar name=7A x=['7A'] y=[81.42]
type=bar name=7B x=['7B'] y=[77.58]

Keluaran memperlihatkan konsekuensi pemetaan. Satu argumen color="kelas" dikompilasi menjadi dua trace, satu per kelas, dan masing-masing membawa nilai x serta y miliknya. Dengan demikian, pemetaan estetika tidak hilang di plotly, melainkan diterjemahkan ke struktur trace, dan pembaca dapat memeriksanya langsung pada objek figur. Perbedaan lain juga tampak pada demo, yaitu agregasi dikerjakan dengan pandas terlebih dahulu karena plotly express tidak menyediakan lapisan statistik setara stat_summary.

Pilihan antara keduanya mengikuti tempat hasilnya dipublikasikan. Laporan cetak dan gambar yang ditempel pada dokumen lebih cepat dikerjakan dengan plotnine, sedangkan dasbor dan halaman web yang memerlukan hover serta zoom lebih cocok dengan plotly express. Karena keduanya berbagi kalimat gramatika, peralihan dari satu ke yang lain hanya berarti menerjemahkan klausa, bukan menyusun mental model dari awal.

Perbandingan keluarga gramatika#

Tiga implementasi berikut mewakili cara gramatika diwujudkan saat ini. ggplot2 dan plotnine mewakili model komposisi lapisan, plotly express mewakili API gramatika yang menghasilkan figur web, sedangkan Vega-Lite mewakili spesifikasi deklaratif berbasis JSON untuk web. Tabel berikut menyandingkan ketiganya pada aspek-aspek yang telah dibahas sepanjang modul ini.

Aspekggplot2 (R) dan plotnine (Python)plotly expressVega-Lite
Bentuk spesifikasifungsi lapisan dirangkai dengan tanda +pemanggilan fungsi px dengan argumen pemetaandokumen JSON deklaratif
Lapisan statistikeksplisit di dalam grafik, misalnya stat_summaryumumnya agregasi lebih dahulu dengan pandastransformasi di dalam spesifikasi, misalnya aggregate
Saluran pemetaanestetika melalui aesargumen x, y, color, dan sizeencoding pada tiap mark
Keluaran utamagambar statis, plotnine merender melalui matplotlibfigur web interaktiffigur web interaktif

Ketiganya membagi kosakata yang sama, yaitu data, pemetaan, mark, statistik, skala, dan panduan, sehingga kemampuan membaca satu implementasi langsung berpindah ke dua lainnya. Pada dokumentasi Vega-Lite, daftar saluran pada halaman encoding memperlihatkan kosakata yang sama dengan estetika ggplot2, hanya ditulis sebagai pasangan bidang dan saluran di dalam JSON.

Ringkasan#

  • ggplot2 di R adalah asal gramatika, dan plotnine meneruskan bentuk rangkaian lapisan dengan tanda tambah ke Python.
  • plotly express menyusun figur dari argumen pemetaan dan mengembalikan struktur JSON berisi trace yang siap dirender interaktif.
  • Vega-Lite menuliskan pemetaan sebagai encoding di dalam dokumen JSON deklaratif, dengan kosakata yang sama di ketiga implementasi.

Referensi#