dtype adalah properti yang paling sering berubah tanpa memberi tahu kita. Satu sel kosong di CSV bisa mengubah kolom int64 menjadi float64; satu operasi gabung bisa mengubah kolom integer menjadi teks; dan astype yang salah menebak langsung melempar error. Chapter ini melatih cara memeriksa dtype dengan df.dtypes dan Series.dtype, memahami kenapa kolom integer berubah menjadi float64, serta membaca error konversi agar perbaikannya tepat sasaran.
Membaca dtype dengan Dua Pintu #
pandas menyediakan dua tampilan yang saling melengkapi. df.dtypes mengembalikan satu Series yang berisi dtype setiap kolom, cocok untuk melihat keseluruhan bentuk data sekaligus. df["nama"].dtype membaca dtype satu kolom saja, cocok untuk perbandingan satu-satu di dalam skrip. Keduanya baca-saja, jadi kita bisa memanggilnya kapan pun tanpa risiko mengubah data. Pemeriksaan dtype paling efektif dilakukan tepat setelah membaca data, sebelum transformasi lain menutupi jejaknya. Script berikut membaca CSV transaksi toko, membandingkan hasilnya dengan bentuk yang diharapkan, lalu menunjukkan cara memulihkan dtype yang bergeser.
import pandas as pd
from io import StringIO
csv = """kode,nama,jumlah,harga_satuan
TRX-001,Budi,2,15000
TRX-002,Siti,,20000
TRX-003,Dewi,1,
TRX-004,Rian,5,12000"""
transaksi = pd.read_csv(StringIO(csv))
harapan = pd.DataFrame({"jumlah": [2, 3, 1, 5]})
def banding_dtype(kiri: pd.Series, kanan: pd.Series, label: str) -> None:
"""Cetak label ketika dtype dua Series tidak sama."""
if kiri.dtype != kanan.dtype:
print(f"{label}: {kiri.dtype} vs {kanan.dtype}")
print("--- dtype hasil read_csv ---")
print(transaksi.dtypes.to_dict())
print("baris yang memuat NaN:")
print(transaksi[transaksi.isna().any(axis=1)].to_string(index=False))
print()
print("--- df.dtypes vs Series.dtype ---")
print("df.dtypes ->", type(transaksi.dtypes).__name__)
print("df['jumlah'].dtype ->", transaksi["jumlah"].dtype)
print()
print("--- teks memakai dtype str bawaan 3.0 ---")
print("dtype kolom nama :", transaksi["nama"].dtype)
print("sama dengan 'str'?", transaksi["nama"].dtype == "str")
print()
print("--- membandingkan dtype dengan frame harapan ---")
banding_dtype(transaksi["jumlah"], harapan["jumlah"], "jumlah")
print("penyebabnya: NaN di kolom jumlah menaikkan int64 menjadi float64")
print()
print("--- convert_dtypes memulihkan integer ---")
print(transaksi.convert_dtypes().dtypes.to_dict())
print()
print("--- astype yang ditolak ---")
teks = pd.Series(["10", "2x"])
try:
teks.astype(int)
except ValueError as exc:
print("astype(int) ->", str(exc).splitlines()[0])
try:
teks.astype(float)
except ValueError as exc:
print("astype(float) ->", str(exc).splitlines()[0])
print("to_numeric coerce:", pd.to_numeric(teks, errors="coerce").tolist())Output yang Dihasilkan:
--- dtype hasil read_csv ---
{'kode': <StringDtype(na_value=nan)>, 'nama': <StringDtype(na_value=nan)>, 'jumlah': dtype('float64'), 'harga_satuan': dtype('float64')}
baris yang memuat NaN:
kode nama jumlah harga_satuan
TRX-002 Siti NaN 20000.0
TRX-003 Dewi 1.0 NaN
--- df.dtypes vs Series.dtype ---
df.dtypes -> Series
df['jumlah'].dtype -> float64
--- teks memakai dtype str bawaan 3.0 ---
dtype kolom nama : str
sama dengan 'str'? True
--- membandingkan dtype dengan frame harapan ---
jumlah: float64 vs int64
penyebabnya: NaN di kolom jumlah menaikkan int64 menjadi float64
--- convert_dtypes memulihkan integer ---
{'kode': <StringDtype(na_value=<NA>)>, 'nama': <StringDtype(na_value=<NA>)>, 'jumlah': Int64Dtype(), 'harga_satuan': Int64Dtype()}
--- astype yang ditolak ---
astype(int) -> invalid literal for int() with base 10: '2x'
astype(float) -> could not convert string to float: '2x'
to_numeric coerce: [10.0, nan]Mari kita bedah bagian pentingnya:
transaksi.dtypes.to_dict(): kolomjumlahdanharga_satuanterbaca sebagaifloat64, bukan integer. Penyebabnya terlihat pada dua baris ber-NaN: sel kosong milik Siti di kolomjumlahdan sel kosong milik Dewi di kolomharga_satuan.NaNtidak punya representasi integer, sehingga pandas memilihfloat64yang bisa menampungnya.type(transaksi.dtypes).__name__: hasilnyaSeries, mengingatkan kita bahwadf.dtypesadalah objek pandas biasa yang bisa diindex, dibandingkan, atau dijadikan mask seperti Series lainnya.transaksi["nama"].dtype == "str": di pandas 3.0, kolom teks bawaan memakai dtypestr(bukanobjectseperti versi lama), dan nilai hilangnyaNaN. Pemeriksaan teks yang lama sepertidtype == objectakan melaporkanFalsepada data 3.0 yang bersih.- Fungsi
banding_dtype(): helper kecil yang membandingkan dtype dua Series dan mencetak baris laporan hanya saat keduanya berbeda. Pola “bandingkan dengan bentuk harapan” inilah inti debugging dtype: hasil pembacaan dibandingkan terhadap kontrak, bukan terhadap perasaan. transaksi.convert_dtypes(): memulihkan kolom yang isinya tetap bulat menjadi dtype nullableInt64—jumlahdanharga_satuankembali terbaca sebagai integer sambil tetap menampungNaN. Perhatikan kolom teks ikut berpindah ke dtypestringdengan nilai hilangpd.NA, jadi konversi ini juga mengubah perilaku perbandingan nilai hilang.teks.astype(int): melemparValueErrordengan pesaninvalid literal for int() with base 10: '2x'. Pesan itu menunjuk nilai persis yang gagal, sehingga perbaikan bisa diarahkan ke baris data tersebut. Alternatif yang lebih toleran adalahpd.to_numeric(teks, errors="coerce"), yang mengubah nilai bermasalah menjadiNaNdan melanjutkan proses.
Peta Perbaikan dtype yang Sering Dibutuhkan #
| Situasi | Alat yang tepat |
|---|---|
Kolom angka jadi float64 karena NaN | convert_dtypes() untuk kembali ke Int64, atau fillna() bila NaN memang harus diisi |
| Teks angka yang bersih | astype(int) / astype(float) |
| Teks angka yang mungkin kotor | pd.to_numeric(..., errors="coerce") lalu periksa NaN yang baru muncul |
| Ingin melihat dtype sekaligus jumlah baris terisi | df.info() |
dtype yang tidak sesuai harapan adalah salah satu bentuk “kode benar, data salah”. Masalah sebaliknya — kode yang belum terbukti benar — membutuhkan pengujian terprogram, dan itulah materi section ini pada chapter berikutnya: Menguji DataFrame dengan pytest.
Referensi resmi untuk chapter ini: pandas.DataFrame.dtypes , pandas.DataFrame.convert_dtypes , dan Working with missing data .