Fungsi crosstab menghitung tabel frekuensi silang antara dua kolom kategori dan menjadi penutup modul pengubahan bentuk. Topik ini membahas frekuensi silang ruang terhadap status sensor, proporsi per baris dengan normalize, agregasi nilai dengan values dan aggfunc, serta penerapannya sebagai laporan ringkas kondisi sensor per ruang pada dataset kontrak 96 baris.
crosstab menghitung frekuensi silang#
Fungsi crosstab menjumlahkan banyaknya baris untuk setiap pasangan kategori dari dua kolom, lalu menyusun hasilnya sebagai tabel lebar dengan baris dan kolom kategori. Bangun dataset kontrak log sensor berikut sebagai bahan seluruh topik ini.
import numpy as np
import pandas as pd
rng = np.random.default_rng(42)
n = 96
df = pd.DataFrame({
"waktu": pd.date_range("2026-01-05 07:00", periods=n, freq="15min"),
"ruang": rng.choice(["Lab A", "Lab B", "Ruang Arsip"], n, p=[0.4, 0.35, 0.25]),
"suhu_c": np.round(rng.normal(24, 1.5, n), 1),
"lembap_pct": np.round(rng.normal(60, 5, n), 1),
"status_sensor": rng.choice(["normal", "kalibrasi", "rusak"], n, p=[0.85, 0.10, 0.05]),
})
df.to_csv("sensor_log.csv", index=False) # disimpan agar blok berikutnya cukup membaca berkas ini
print(len(df))96Baca kembali berkasnya, lalu hitung tabulasi silang ruang terhadap status sensor dengan satu panggilan. Kedua argumennya berupa deret kategori, bukan nama kolom pada satu DataFrame, sehingga crosstab juga dapat memadukan kolom dari sumber yang berbeda.
import pandas as pd
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
print(pd.crosstab(df["ruang"], df["status_sensor"]))status_sensor kalibrasi normal rusak
ruang
Lab A 3 32 1
Lab B 5 31 2
Ruang Arsip 3 19 0Barisnya adalah nilai unik ruang dan kolomnya adalah nilai unik status_sensor, dengan urutan alfabetis pada keduanya. Setiap sel menghitung baris yang memiliki pasangan kategori tersebut, misalnya terdapat dua bacaan berstatus rusak di Lab B dan nol di Ruang Arsip. Di balik layar, crosstab merupakan kasus khusus pivot_table dengan agregasi hitung, sehingga tempatnya yang wajar memang pada keluarga pengubah bentuk ini.
Proporsi per baris dengan normalize#
Frekuensi mentah sulit dibandingkan apabila jumlah baris tiap kategori berbeda jauh, dan parameter normalize mengubah frekuensi menjadi proporsi. Nilai normalize="index" membagi setiap sel dengan total barisnya, sehingga jumlah proporsi tiap baris tepat satu.
import pandas as pd
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
print(pd.crosstab(df["ruang"], df["status_sensor"], normalize="index").round(2))status_sensor kalibrasi normal rusak
ruang
Lab A 0.08 0.89 0.03
Lab B 0.13 0.82 0.05
Ruang Arsip 0.14 0.86 0.00Setiap baris berjumlah 1.00, misalnya Lab A memuat 0.08 ditambah 0.89 ditambah 0.03, dan pembulatan dua desimal menyisakan selisih yang dapat diabaikan. Proporsi memperlihatkan hal yang tidak tampak pada frekuensi mentah, yaitu porsi kalibrasi tertinggi justru berada di Ruang Arsip meskipun jumlah bacaannya paling sedikit. Nilai lain yang tersedia adalah "columns" untuk proporsi per kolom dan "all" untuk proporsi terhadap seluruh tabel, sehingga sudut pandangnya dapat dipilih sesuai kebutuhan laporan.
Rata-rata suhu dengan values dan aggfunc#
Parameter values beserta aggfunc mengganti isi sel dari hitungan frekuensi menjadi agregasi kolom nilai lain, sebagaimana pivot_table pada topik pivot. Contoh berikut menghitung rata-rata suhu untuk setiap pasangan ruang dan status.
import pandas as pd
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
print(pd.crosstab(df["ruang"], df["status_sensor"], values=df["suhu_c"], aggfunc="mean").round(1))status_sensor kalibrasi normal rusak
ruang
Lab A 23.3 23.7 25.3
Lab B 23.4 23.8 25.0
Ruang Arsip 23.4 24.4 NaNSel Ruang Arsip untuk status rusak berupa NaN karena tidak ada baris dengan kombinasi itu, sebagaimana ditunjukkan tabel frekuensi yang selnya nol. Pola yang tampak cukup konsisten, yaitu bacaan berstatus rusak cenderung berasal dari suhu yang lebih tinggi daripada status lain. Kombinasi values dan aggfunc dengan demikian menjadikan crosstab bukan sekadar penghitung, melainkan penyusun ringkasan beragregasi pada kerangka silang yang sama.
Laporan ringkas kondisi sensor per ruang#
Ketiga tabel di atas menyusun laporan kondisi sensor yang siap diserahkan tanpa pengolahan tambahan. Tabel frekuensi menjadi bagian volumetriknya, yaitu Lab A mencatat 32 bacaan normal, 3 kalibrasi, dan 1 rusak, Lab B mencatat 31 normal, 5 kalibrasi, dan 2 rusak, sedangkan Ruang Arsip mencatat 19 normal, 3 kalibrasi, dan 0 rusak. Sel nol pada Ruang Arsip penting dicatat karena berarti tidak ada sensor yang gagal total, bukan bahwa data itu hilang.
Tabel proporsi menjadi bagian perbandingannya karena jumlah bacaan per ruang tidak seimbang, yaitu 36 untuk Lab A, 38 untuk Lab B, dan 22 untuk Ruang Arsip. Porsi bacaan normal tertinggi dimiliki Lab A pada 0.89, sedangkan porsi kalibrasi tertinggi dimiliki Ruang Arsip pada 0.14. Tabel rata-rata suhu melengkapi laporan dengan petunjuk teknis, karena kedua sel berstatus rusak berasal dari suhu sekitar 25 derajat, lebih tinggi daripada status lain pada baris yang sama. Untuk laporan mingguan, kombinasi tiga tabel ini cukup, dan tabelnya dapat diperbarui hanya dengan mengganti sumber df tanpa mengubah satu pun baris kodenya.
Ringkasan#
crosstabmenghitung frekuensi silang dua kolom kategori dan merupakan kasus khususpivot_tabledengan agregasi hitung.normalize="index"mengubah frekuensi menjadi proporsi per baris, dengan pilihan"columns"dan"all"untuk sudut pandang lain.valuesbesertaaggfuncmengganti hitungan dengan agregasi kolom nilai, dan kombinasi tanpa baris tetap berupaNaN.
Referensi#
- pandas.crosstab — pandas
— Dokumentasi resmi
crosstabbeserta parameter normalize, values, dan aggfunc. - Reshaping and pivot tables — pandas — Panduan resmi pengubahan bentuk DataFrame pada pandas.