Parquet menghemat ruang penyimpanan, tetapi kompresi dan metadata yang padat membuat proses baca-tulisnya bukan yang tercepat. Ketika kebutuhan kita bukan arsip jangka panjang melainkan pemindahan data secepat mungkin antara pandas dan alat lain, misalnya antara notebook analisis dan layanan yang dibangun di atas Apache Arrow, format Feather adalah jawabannya. Feather menyimpan DataFrame hampir persis seperti bentuknya di memori, sehingga membaca dan menulisnya nyaris tanpa kerja konversi. Chapter ini, chapter terakhir sebelum kita menjelajah sumber data web dan database, membahas cara menulis dan membaca Feather dengan bantuan pyarrow.
Feather dan Ekosistem Arrow #
Feather adalah format berbasis Apache Arrow yang menyimpan tabel dalam susunan kolom, mirip Parquet, tetapi dengan pengodean yang jauh lebih sederhana. Arrow sendiri adalah standar representasi data kolom di memori yang dipakai banyak alat data modern, sehingga file Feather menjadi bahasa bersama di antara alat-alat tersebut. Tabel berikut menempatkan Feather di antara dua format yang sudah kita kuasai:
| Format | Kekuatan utama | Cocok untuk |
|---|---|---|
| CSV | Teks polos, dibuka di mana saja | Pertukaran dengan manusia dan aplikasi apa pun |
| Parquet | Kompresi padat dan statistik kolom | Arsip dan penyimpanan data besar jangka panjang |
| Feather | Baca-tulis paling cepat, dekat dengan bentuk memori | Pertukaran data cepat antar-alat dalam satu pipeline |
Karena isi file Feather hampir sama dengan tata letak memori Arrow, read_feather() tidak perlu mengurai teks dan hanya menjalankan kompresi ringan. Inilah alasan Feather disebut format pertukaran (interchange format): kekuatannya pada kecepatan, bukan pada hemat ruang.
Menyimpan dan Membaca Feather #
Skrip berikut menyimpan tabel penjualan yang memuat kolom tanggal, lalu membacanya kembali dan memeriksa kesamaannya dengan DataFrame asal:
import pandas as pd
from pathlib import Path
penjualan = pd.DataFrame({
"transaksi": [1, 2, 3, 4],
"produk": ["Kopi Gayo", "Teh Melati", "Gula Aren", "Kopi Gayo"],
"jumlah": [12, 30, 25, 8],
"harga": [85000, 32000, 24000, 85000],
"tanggal": pd.to_datetime(["2026-01-05", "2026-01-06", "2026-01-07", "2026-01-08"]),
})
penjualan.to_feather("penjualan.feather")
df = pd.read_feather("penjualan.feather")
print(df)
print()
print(df.dtypes)
print()
print(df.equals(penjualan))
Path("penjualan.feather").unlink()Output yang Dihasilkan:
transaksi produk jumlah harga tanggal
0 1 Kopi Gayo 12 85000 2026-01-05
1 2 Teh Melati 30 32000 2026-01-06
2 3 Gula Aren 25 24000 2026-01-07
3 4 Kopi Gayo 8 85000 2026-01-08
transaksi int64
produk str
jumlah int64
harga int64
tanggal datetime64[us]
dtype: object
TrueMari kita uraikan:
- Baris 4-9 (
penjualan = pd.DataFrame({...})): DataFrame contoh dibangun dengan lima kolom; kolomtanggaldibuat lewatpd.to_datetime()sehingga bertipedatetime64[us], resolusi mikrodetik standar pandas 3.0. - Baris 11 (
penjualan.to_feather("penjualan.feather")): methodto_feather()menulis seluruh DataFrame beserta metadata tipe setiap kolom ke satu file Feather; nama file adalah satu-satunya argumen wajib. - Baris 13-14 (
df = pd.read_feather(...)): pembacaan mengembalikan DataFrame baru;dtypesmenunjukkanstr,int64, dandatetime64[us]tidak berubah sama sekali karena skema tersimpan eksplisit di file. - Baris 18 (
df.equals(penjualan)): hasilTruemenegaskan round trip Feather tidak mengubah nilai, tipe data, maupun index default.
Tidak ada proses menebak tipe seperti pada CSV dan JSON; skema ikut tersimpan, dan itulah sumber kesetaraan penuh tersebut.
Posisi Feather di Antara Format Lain #
Untuk melihat posisi Feather secara konkret, skrip berikut menyimpan tabel 12.000 baris yang sama dalam tiga format sekaligus lalu membandingkan ukuran filenya:
import pandas as pd
from pathlib import Path
n = 12000
produk = ["Kopi Gayo", "Teh Melati", "Gula Aren", "Kopi Robusta"]
kota = ["Bandung", "Jakarta", "Surabaya", "Medan"]
penjualan = pd.DataFrame({
"transaksi": range(1, n + 1),
"produk": [produk[i % 4] for i in range(n)],
"kota": [kota[i % 4] for i in range(n)],
"jumlah": [(i % 30) + 1 for i in range(n)],
})
penjualan.to_csv("penjualan.csv", index=False)
penjualan.to_feather("penjualan.feather")
penjualan.to_parquet("penjualan.parquet", index=False)
print("Jumlah baris :", len(penjualan))
print("Ukuran file CSV :", Path("penjualan.csv").stat().st_size, "byte")
print("Ukuran file Feather:", Path("penjualan.feather").stat().st_size, "byte")
print("Ukuran file Parquet:", Path("penjualan.parquet").stat().st_size, "byte")
Path("penjualan.csv").unlink()
Path("penjualan.feather").unlink()
Path("penjualan.parquet").unlink()Output yang Dihasilkan:
Jumlah baris : 12000
Ukuran file CSV : 318323 byte
Ukuran file Feather: 148978 byte
Ukuran file Parquet: 72860 byteFeather berada di tengah: sekitar dua kali lebih kecil dari CSV berkat kompresi lz4 bawaan, tetapi sekitar dua kali lebih besar dari Parquet yang menekan data jauh lebih agresif. Angka ini konsisten dengan desainnya; kompresi yang ringan membuat penulisan dan pembacaan Feather cepat, sementara kompresi padat Parquet memakan waktu lebih banyak di kedua arah. Ukuran file pun bukan satu-satunya pertimbangan, karena keunggulan Feather paling terasa ketika data bolak-balik berkali-kali dalam satu alur kerja, bukan ketika disimpan bertahun-tahun.
Kapan Feather Dipilih #
Pilih Feather ketika data harus berpindah cepat antar-alat yang sama-sama memahami Arrow: menyimpan hasil antara dari notebook lalu melanjutkannya di skrip lain, mengoper tabel dari pandas ke engine analitik lain, atau menuliskan DataFrame ke disk agar perhitungan berat tidak perlu diulang. Untuk arsip jangka panjang, dataset yang dibagikan ke banyak tim, atau tabel besar yang biasanya dibaca sebagian kolom, Parquet tetap pilihan yang lebih bijak.
Sampai titik ini semua format yang kita bahas berupa file yang sudah ada di disk. Chapter berikutnya melangkah ke sumber yang lebih dinamis: tabel yang tertanam di halaman web, yang bisa ditarik pandas langsung menjadi DataFrame dengan read_html().