Sebelum menguji apa pun, kita perlu melihat datanya. Statistik deskriptif adalah alat lihatnya: satu baris per metode yang memuat ukuran pusat, sebaran, dan ketidakpastian estimasi. Pada bagian ini kita membangun statistikKelompok, membaca tabelnya dengan benar, lalu melengkapi angka dengan box plot pembanding yang digambar manual tanpa Statistics Toolbox.
Yang kita bangun pada bagian ini:
statistikKelompok.m— n, mean, std, median, SE, dan CI95 per metode dalam satu struct array,- cara membaca tabelnya — beda std, standard error, dan confidence interval,
- pemilihan mean vs median dan kaitannya dengan normalitas,
- box plot manual dari
quantile+ primitif grafik sebagai pemeriksaan visual.
Dari Rumus ke Struct: statistikKelompok.m #
Delapan statistik per kelompok dihitung langsung dari rumusnya — bukan dari toolbox:
| Statistik | Rumus | Makna |
|---|---|---|
| n | banyaknya replikat | ukuran sampel |
| mean | jumlah x / n | pusat sebaran |
| std | sqrt(sum((x-mean)^2) / (n-1)) | sebaran pengamatan (sampel) |
| median | nilai tengah data terurut | pusat yang tahan outlier |
| SE | std / sqrt(n) | ketidakpastian mean |
| CI95 | mean +/- 1.96 * SE | rentang mean populasi (aproksimasi z) |
| min, max | ekstrem data | jangkauan pengamatan |
Berkas src/statistikKelompok.m berikut menerima struct dari buatDataEksperimen, mengembalikan struct array 1x3, dan mencetak tabel rapi saat diminta:
function S = statistikKelompok(data, cetak)
% STATISTIKELOMPOK Statistik ringkas tiap kelompok perlakuan.
% S = statistikKelompok(data) : hitung dan cetak tabel ringkas.
% S = statistikKelompok(data, false) : hitung tanpa mencetak.
%
% data : struct keluaran buatDataEksperimen (.label, .waktu, .n)
% S : struct array 1x3, satu per metode, dengan field:
% n - jumlah replikat
% mean - rata-rata
% std - simpangan baku sampel (pembagi n-1)
% median- nilai tengah
% se - standard error of the mean, std/sqrt(n)
% ci95 - interval kepercayaan 95 persen, mean +/- 1.96*se
% (aproksimasi z; lihat catatan di Bagian 2)
% min, max - pengamatan terkecil dan terbesar
if nargin < 2 || isempty(cetak)
cetak = true;
end
k = numel(data.label);
% Kerangka struct supaya semua elemen punya field yang sama.
S = repmat(struct('n', 0, 'mean', 0, 'std', 0, 'median', 0, ...
'se', 0, 'ci95', [0 0], 'min', 0, 'max', 0), 1, k);
if cetak
fprintf('%-6s %4s %7s %7s %7s %6s %7s %7s %6s %6s\n', ...
'Metode', 'n', 'mean', 'std', 'median', 'SE', ...
'CI95-', 'CI95+', 'min', 'max');
end
for i = 1:k
x = data.waktu(i, :);
S(i).n = numel(x);
S(i).mean = mean(x);
S(i).std = std(x); % sampel: pembagi n-1
S(i).median = median(x);
S(i).se = S(i).std / sqrt(S(i).n);
S(i).ci95 = S(i).mean + [-1, 1] * 1.96 * S(i).se;
S(i).min = min(x);
S(i).max = max(x);
if cetak
fprintf('%-6s %4d %7.2f %7.2f %7.2f %6.2f %7.2f %7.2f %6.2f %6.2f\n', ...
data.label{i}, S(i).n, S(i).mean, S(i).std, S(i).median, ...
S(i).se, S(i).ci95(1), S(i).ci95(2), S(i).min, S(i).max);
end
end
endMari kita bedah baris-baris kode di atas:
- Baris 17-19 (
if nargin < 2 ... cetak = true;): argumen kedua opsional. PanggilanstatistikKelompok(data)mencetak tabel;statistikKelompok(data, false)hanya mengembalikan struct — jalur yang dipakai uji otomatis dan laporan di Bagian 4. - Baris 24-25 (
S = repmat(struct('n', 0, ...), 1, k);): kerangka struct dengan seluruh field dideklarasikan di awal. Semua elemenSdijamin punya field yang sama, sehinggaS(i).mean = ...tidak pernah menambah field secara kebetulan. - Baris 37 (
S(i).std = std(x);):stdMATLAB dan Octave memakai normalisasi sampel (pembagi n-1) secara default — persis rumus tabel di atas. Normalisasi populasi (pembagi n) hanya muncul lewat argumen keduastd(x, 1)dan tidak kita pakai. - Baris 39 (
S(i).se = S(i).std / sqrt(S(i).n);): standard error menyusut mengikuti sqrt(n) — replikat empat kali lebih banyak memangkas ketidakpastian mean hanya separuhnya. - Baris 40 (
S(i).ci95 = S(i).mean + [-1, 1] * 1.96 * S(i).se;): vektor[-1, 1]dikalikan skalar menghasilkan batas bawah dan atas sekaligus dalam satu ekspresi, tanpa dua baris terpisah. - Baris 43-46 (
fprintf('%-6s %4d %7.2f ...): satu formatfprintfuntuk satu baris tabel — lebar kolom tetap (%-6s,%7.2f) menjaga kolom rata kanan antar baris. Argumen yang dicetak semuanya skalar, menghindari perilaku flattenfprintfpada argumen array.
Menjalankan fungsi tersebut:
% driver: statistik deskriptif seluruh metode
data = buatDataEksperimen();
S = statistikKelompok(data);Output yang Dihasilkan:
Metode n mean std median SE CI95- CI95+ min max
A 10 50.00 1.90 49.65 0.60 48.82 51.18 47.30 52.90
B 10 45.00 1.95 44.90 0.62 43.79 46.21 42.60 47.60
C 10 52.00 2.83 51.80 0.89 50.25 53.75 48.50 56.10Struct array memudahkan akses lintas metode: [S.mean] menjadi [50 45 52], [S.se] menjadi [0.60 0.62 0.89] — pola comma-list yang dipakai orkestrator di Bagian 4 untuk mencari metode tercepat.
std, SE, dan CI95: Tiga Angka yang Sering Tertukar #
Ketiganya berpangkal dari data yang sama tetapi menjawab pertanyaan berbeda:
| Ukuran | Pertanyaan yang dijawab | Metode A |
|---|---|---|
| std = 1.90 | seberapa menyebar satu batch ke batch lain? | sebaran individual |
| SE = 0.60 | seberapa pasti kita mengetahui mean populasi? | ketidakpastian estimasi |
| CI95 = [48.82, 51.18] | di rentang mana mean populasi barangkali berada? | interval dari SE |
Kesalahan paling umum: melaporkan 50.00 +/- 1.90 (mean +/- std) seolah angka 1.90 adalah ketidakpastian mean. Padahal dengan 10 replikat, ketidakpastian mean hanya 1.90/sqrt(10) = 0.60 menit. Konsekuensinya besar: membandingkan dua mean lewat std akan menyimpulkan “beda wajar”, padahal lewat SE kedua mean terpisah meyakinkan.
Membaca CI kolom per kolom juga informatif sebelum uji formal. CI95 metode B [43.79, 46.21] dan metode A [48.82, 51.18] tidak tumpang tindih sama sekali — indikasi awal bahwa A dan B berbeda. Sebaliknya CI A dan C [50.25, 53.75] bertumpang tindih di [50.25, 51.18] — konsisten dengan posthoc Bagian 3 yang menyimpulkan keduanya tidak berbeda signifikan. Indikasi visual seperti ini tidak menggantikan uji; ujilah yang memutuskan.
Mean atau Median #
Mean adalah pilihan utama karena analisis lanjutan kita (uji t dan ANOVA) menguji perbedaan mean. Median menjadi andalan ketika sebaran miring atau ber-outlier — satu pencilan ekstrem menggeser mean jauh sementara median stabil. Praktik yang sehat: hitung keduanya. Bila mean dan median jauh berbeda, itu tanda kemiringan yang perlu ditindaklanjuti.
Di data kita keduanya nyaris berimpit: mean A 50.00 vs median 49.65; B 45.00 vs 44.90; C 52.00 vs 51.80. Selisih kecil ini menjadi petunjuk pertama bahwa sebaran tiap metode cukup simetris — dugaan yang akan diuji angka kemiringan pada Bagian 3.
Box Plot Pembanding #
Angka di tabel perlu dicek mata. Box plot memampatkan sebaran tiap metode menjadi lima bilangan — Q1, median, Q3, whisker, outlier — sehingga posisi dan lebar sebaran antar metode terbaca sekali pandang. Karena boxplot milik Statistics Toolbox dan boxchart tidak ada di Octave, kotaknya kita gambar sendiri dengan pola quantile + fill + line dari chapter Box Plot. Fungsi berikut tinggal sebagai subfunction gambarBoxPlot di dalam jalankanAnalisis.m yang dirakit penuh pada Bagian 4:
function ringkasan = gambarBoxPlot(data, namaFile)
% GAMBARBOXPLOT Box plot manual dari kuartil dan primitif grafik.
% Pola quantile + fill + line (chapter Box Plot) supaya bekerja
% tanpa Statistics Toolbox. Rangkum juga lima bilangan tiap kotak
% agar angka laporan dan grafik datang dari perhitungan yang sama.
k = numel(data.label);
ringkasan = repmat(struct('q1', 0, 'median', 0, 'q3', 0, ...
'whiskerBawah', 0, 'whiskerAtas', 0, 'jumlahOutlier', 0), 1, k);
f = figure('visible', 'off');
hold on;
for i = 1:k
x = data.waktu(i, :);
q = quantile(x, [0.25, 0.5, 0.75]);
q1 = q(1);
q2 = q(2);
q3 = q(3);
iqr = q3 - q1;
lo = q1 - 1.5 * iqr; % batas bawah pencilan
hi = q3 + 1.5 * iqr; % batas atas pencilan
wl = min(x(x >= lo)); % ujung whisker = data nyata
wu = max(x(x <= hi));
outlier = x(x < lo | x > hi);
w = 0.3; % setengah lebar kotak
fill([i-w, i+w, i+w, i-w], [q1, q1, q3, q3], ...
[0.8, 0.85, 0.95], 'EdgeColor', 'k');
line([i-w, i+w], [q2, q2], 'Color', 'r', 'LineWidth', 2);
line([i, i], [q1, wl], 'Color', 'k');
line([i, i], [q3, wu], 'Color', 'k');
line([i-w/2, i+w/2], [wl, wl], 'Color', 'k');
line([i-w/2, i+w/2], [wu, wu], 'Color', 'k');
if ~isempty(outlier)
plot(i * ones(size(outlier)), outlier, 'r+', 'LineWidth', 1.5);
end
ringkasan(i).q1 = q1;
ringkasan(i).median = q2;
ringkasan(i).q3 = q3;
ringkasan(i).whiskerBawah = wl;
ringkasan(i).whiskerAtas = wu;
ringkasan(i).jumlahOutlier = numel(outlier);
end
hold off;
set(gca, 'XTick', 1:k, 'XTickLabel', data.label);
xlabel('Metode');
ylabel('Waktu produksi (menit)');
title('Distribusi waktu produksi per metode');
saveas(f, namaFile);
delete(f);
endBagian inilah yang mencetak baris lima bilangan saat pipeline penuh dijalankan (output berikut diambil dari jalankanAnalisis() — lengkapnya di Bagian 4):
--- Box plot per metode ---
A: Q1=48.5 med=49.65 Q3=51.6 whisker=47.3-52.9 outlier=0
B: Q1=43.1 med=44.9 Q3=46.8 whisker=42.6-47.6 outlier=0
C: Q1=49.1 med=51.8 Q3=54.7 whisker=48.5-56.1 outlier=0
Grafik tersimpan: box-plot-eksperimen.pngBeberapa hal penting dari fungsi tersebut:
q = quantile(x, [0.25, 0.5, 0.75]);— tiga kuartil sekaligus; IQR dan batas pencilan (1.5 x IQR) dihitung dari situ, sama dengan definisi defaultboxplot.wl/wu— ujung whisker harus observasi data nyata:min/maxdengan mask logis memilih kandidat di dalam batas pencilan.fill+line+plot— kotak poligon, garis median merah, whisker dan tutupnya, serta penanda+untuk pencilan.figure('visible', 'off')+saveas+delete— pola headless: gambar dibuat tanpa jendela, disimpan sebagai PNG, lalu figur dibebaskan.ringkasan— lima bilangan dikembalikan sebagai struct, bukan sekadar digambar; orkestrator mencetaknya sehingga angka di laporan dan bentuk di grafik dijamin berasal dari perhitungan yang sama.
Membaca Visual vs Angka #
Grafik dan tabel saling menguatkan: kotak B duduk jelas di bawah kotak A dan C (median 44.9 vs 49.65 dan 51.8) — sejalan dengan mean 45 vs 50 dan 52. Kotak C tampak paling tinggi sekaligus paling panjang (Q1 49.1 ke Q3 54.7, IQR 5.6 menit) — sejalan dengan std 2.83 yang memang didesain lebih lebar dari A dan B. Kotak A dan C bertumpang tindih di hampir seluruh tingginya, sementara keduanya terpisah bersih dari B. Tidak ada pencilan di ketiga metode — sebaran yang bersih, tidak ada batch anomali yang menuntut pemeriksaan khusus.
Deskriptif sudah memberi gambaran. Bagian 3 menguji apakah pola itu cukup kuat disebut perbedaan nyata: uji normalitas dulu, lalu ANOVA, lalu posthoc Bonferroni.