Analisis yang berhenti di layar notebook belum selesai — hasilnya harus sampai ke orang lain sebagai berkas: CSV untuk tim data, Excel untuk tim bisnis, JSON untuk program lain, dan grafik untuk slide presentasi. Chapter penutup section ini merangkai semuanya: menulis DataFrame ke tiga format tabular, membangun laporan metrik ringkas, mengekspor grafik dengan resolusi yang tepat, dan menamai berkas agar hasil kerja hari ini masih bisa direproduksi bulan depan.

Tiga Format Tabular: CSV, Excel, dan JSON #

Metode to_csv() adalah pintu ekspor pertama yang perlu dikuasai. Parameter penting pertama Anda adalah index=False — tanpa parameter tersebut, kolom index ikut tertulis dan menjadi kolom misterius Unnamed: 0 saat file dibaca ulang:

python
import pandas as pd

df = pd.read_csv("penjualan.csv")
df["total"] = df["harga"] * df["jumlah"]

df.to_csv("penjualan_dengan_total.csv", index=False)
df_baca_ulang = pd.read_csv("penjualan_dengan_total.csv")
print(df_baca_ulang[["tanggal", "kota", "produk", "total"]].head(3))
print()

df.to_excel("penjualan_dengan_total.xlsx", sheet_name="penjualan", index=False)
df_excel = pd.read_excel("penjualan_dengan_total.xlsx")
print("Dimensi hasil read_excel:", df_excel.shape)
print()

print(df.head(2).to_json(orient="records", indent=2, force_ascii=False))

Output yang Dihasilkan:

text
      tanggal      kota                produk   total
0  2025-01-03   Jakarta        Mouse Wireless  600000
1  2025-01-06   Bandung            Kaos Polos  570000
2  2025-01-09  Surabaya  Novel Laskar Pelangi  495000

Dimensi hasil read_excel: (24, 7)

[
  {
    "tanggal":"2025-01-03",
    "kota":"Jakarta",
    "kategori":"Elektronik",
    "produk":"Mouse Wireless",
    "harga":150000,
    "jumlah":4,
    "total":600000
  },
  {
    "tanggal":"2025-01-06",
    "kota":"Bandung",
    "kategori":"Fashion",
    "produk":"Kaos Polos",
    "harga":95000,
    "jumlah":6,
    "total":570000
  }
]

Tiga format tersebut punya peran berbeda. to_csv() menghasilkan file universal yang dibaca semua alat — untuk data yang akan diolah lagi, ini pilihan default. to_excel() menulis lembar kerja sungguhan bernama penjualan yang langsung terbuka di Excel; metode ini membutuhkan package openpyxl (versi 3.1.5 pada lingkungan uji bab ini), sehingga bila muncul ImportError: Missing optional dependency 'openpyxl', pasang dulu dengan pip install openpyxl. to_json() dengan orient="records" menghasilkan satu objek per baris — format yang enak dikonsumsi program lain dan API; parameter force_ascii=False menjaga teks Indonesia tetap terbaca, bukan berubah menjadi \u escape.

Pola Laporan Ringkasan #

Praktik yang sehat: akhir analisis menghasilkan dua lapis keluaran — tabel agregat untuk dibaca manusia, dan sekumpulan metrik kunci. Pola lengkapnya:

python
ringkasan = df.groupby("kategori")["total"].agg(["sum", "mean", "count"]).reset_index()
print(ringkasan.to_markdown(index=False))
print()

metrik = {
    "jumlah_transaksi": len(df),
    "total_pendapatan": int(df["total"].sum()),
    "rata_rata_transaksi": int(df["total"].mean()),
    "unit_terjual": int(df["jumlah"].sum()),
}
laporan = pd.DataFrame(list(metrik.items()), columns=["metrik", "nilai"])
laporan.to_csv("laporan_metrik.csv", index=False)
print(laporan.to_string(index=False))
print()
print(laporan.to_markdown(index=False))

Output yang Dihasilkan:

text
| kategori   |     sum |   mean |   count |
|:-----------|--------:|-------:|--------:|
| Buku       | 2622000 | 374571 |       7 |
| Elektronik | 7300000 | 730000 |      10 |
| Fashion    | 4455000 | 636429 |       7 |

             metrik    nilai
   jumlah_transaksi       24
   total_pendapatan 14377000
rata_rata_transaksi   599041
       unit_terjual       80

| metrik              |    nilai |
|:--------------------|---------:|
| jumlah_transaksi    |       24 |
| total_pendapatan    | 14377000 |
| rata_rata_transaksi |   599041 |
| unit_terjual        |       80 |

Dictionary metrik dikumpulkan dari agregasi satu baris, diubah menjadi DataFrame dua kolom, lalu ditulis tiga arah: to_csv() untuk arsip, to_string() untuk terminal, dan to_markdown() untuk langsung ditempel ke dokumentasi atau wiki. Perlu dicatat bahwa to_markdown() bergantung pada package tabulate — pada lingkungan uji sudah terpasang (versi 0.9.0); bila belum, pandas melempar ImportError dan fallback to_string() di atas sudah cukup untuk tampilan terminal.

Ekspor Grafik: Format dan dpi #

Grafik dari chapter Visualisasi dengan Matplotlib dan Visualisasi dengan Seaborn disimpan lewat fig.savefig(). Tiga keputusannya: format berkas, resolusi dpi, dan nama. Perbandingan resolusi bisa dibuktikan dari ukuran piksel berkas PNG:

python
import os
import struct

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(figsize=(7, 4))
x = np.linspace(0, 10, 100)
ax.plot(x, np.sin(x), label="sin(x)")
ax.set_title("Contoh Grafik untuk Ekspor")
ax.legend()
fig.savefig("grafik_72dpi.png", dpi=72)
fig.savefig("grafik_300dpi.png", dpi=300)
fig.savefig("grafik_vektor.svg")
fig.savefig("grafik_vektor.pdf")

def ukuran_png(nama_berkas):
    with open(nama_berkas, "rb") as berkas:
        berkas.read(16)
        lebar, tinggi = struct.unpack(">II", berkas.read(8))
    return lebar, tinggi

print("72 dpi  :", ukuran_png("grafik_72dpi.png"), "piksel")
print("300 dpi :", ukuran_png("grafik_300dpi.png"), "piksel")
print("berkas svg ada:", os.path.exists("grafik_vektor.svg"))
print("berkas pdf ada:", os.path.exists("grafik_vektor.pdf"))

Output yang Dihasilkan:

text
72 dpi  : (504, 288) piksel
300 dpi : (2100, 1200) piksel
berkas svg ada: True
berkas pdf ada: True

Aritmetikanya transparan: kanvas 7×4 inci pada 72 dpi menghasilkan 7×72 = 504 piksel lebar, sedangkan 300 dpi menghasilkan 2100 piksel. Aturan praktisnya: 72–150 dpi untuk tampilan di layar, 300 dpi untuk cetak, dan format vektor SVG/PDF untuk logo serta grafik yang akan diskalakan bebas — vektor tidak pernah pecah karena geometrinya dihitung ulang saat dirender. Fungsi ukuran_png() di atas membaca dimensi langsung dari header berkas PNG sebagai verifikasi tanpa menebak.

Nama Bermerek Waktu dan Reproducibilitas #

Laporan mingguan bernama laporan_metrik.csv akan menimpa versi lama pada pekan berikutnya. Konvensi mengatasinya: sematkan stempel waktu pada nama berkas:

python
from datetime import datetime

stempel = datetime(2025, 6, 15, 9, 30).strftime("%Y%m%d-%H%M")
print(f"nama berkas versi: laporan_metrik_{stempel}.csv")

Output yang Dihasilkan:

text
nama berkas versi: laporan_metrik_20250615-0930.csv

Pada analisis nyata, ganti nilai tetap tersebut dengan datetime.now() — dan sadari bahwa outputnya memang berubah setiap dijalankan; itulah fungsinya. Format %Y%m%d-%H%M menjaga nama berkas rapi terurut di file explorer.

Satu kewajiban terakhir agar hasil bisa direproduksi: catat bibit acak dan versi library. Generator NumPy modern membuat angka acak dari seed:

python
import numpy as np

rng = np.random.default_rng(42)
sampel = rng.integers(1, 7, size=5)
print("sampel default_rng(42) :", sampel)

rng2 = np.random.default_rng(42)
sampel2 = rng2.integers(1, 7, size=5)
print("ulang default_rng(42)  :", sampel2)
print("sama persis             :", np.array_equal(sampel, sampel2))

Output yang Dihasilkan:

text
sampel default_rng(42) : [1 5 4 3 3]
ulang default_rng(42)  : [1 5 4 3 3]
sama persis             : True

Dua generator dengan seed sama menghasilkan urutan angka identik — inilah yang membuat analisis berbasis sampling dapat diperiksa ulang. Pasangkan seed dengan daftar versi (cara mencetaknya ada di chapter Pengenalan Ekosistem Data Python), dan setiap analisis Anda membawa resep untuk diulang orang lain dari nol.

Dengan chapter ini, satu putaran penuh alur kerja data Python tertutup: array NumPy, DataFrame pandas yang bersih dan teranalisis, grafik matplotlib dan seaborn, hingga berkas hasil yang siap dibagikan. Dua arah lanjutan yang wajar: menyusuri data ke arah model prediktif di Section Machine Learning, atau kembali memperdalam fondasi Python di section-section sebelumnya.