Tipe Data Efisien untuk Mengurangi Memori
Turunkan tipe kolom numerik menjadi int32/float32 dan konversikan kolom string menjadi Categorical untuk mengurangi memori DataFrame hingga 70%.
Tipe Data Efisien untuk Mengurangi Memori adalah pelajaran Pandas & NumPy Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Pandas & NumPy Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Pandas & NumPy Academy mencakup 4 pelajaran total.
Mengapa Tipe Data Memengaruhi Kinerja
Di Pandas, setiap kolom memiliki dtype (tipe data) yang menentukan cara nilai disimpan dalam memori dan kecepatan operasi. Pandas secara bawaan menggunakan tipe berukuran besar saat memuat data: int64 (8 byte per nilai), float64 (8 byte), dan object (bervariasi, sering kali 50–200 byte per string). Untuk jutaan baris, memilih tipe yang lebih kecil dapat mengurangi penggunaan memori sebesar 50–80% dan mempercepat operasi 2–5 kali berkat pemanfaatan cache yang lebih baik.
import pandas as pd
import numpy as np
np.random.seed(0)
df = pd.DataFrame({
'id': np.arange(1000000, dtype='int64'),
'score': np.random.uniform(0, 100, 1000000).astype('float64'),
'category': np.random.choice(['A','B','C','D'], 1000000)
})
mem = df.memory_usage(deep=True)
print('Memory per column:')
print(mem)
print(f'Total: {mem.sum() / 1e6:.1f} MB')Menurunkan Ukuran Kolom Integer
Jika sebuah kolom berisi nilai integer yang masih sesuai dengan rentang yang lebih kecil, turunkan ukurannya dari int64 ke tipe integer yang lebih kecil. pd.to_numeric(series, downcast='integer') secara otomatis memilih tipe integer terkecil yang dapat menampung semua nilai: int8 (–128 hingga 127, 1 byte), int16 (–32768 hingga 32767, 2 byte), int32 (±2 miliar, 4 byte), atau tetap menggunakan int64 jika diperlukan. Kolom int8 menggunakan memori 8 kali lebih sedikit daripada int64.
import pandas as pd
import numpy as np
np.random.seed(0)
df = pd.DataFrame({
'age': np.random.randint(18, 90, 500000).astype('int64'),
'score': np.random.randint(0, 100, 500000).astype('int64'),
'large_id': np.random.randint(0, 2**31, 500000).astype('int64')
})
# Downcast integers
for col in df.select_dtypes('int64').columns:
df[col] = pd.to_numeric(df[col], downcast='integer')
print('Dtypes after downcasting:')
print(df.dtypes)
print(f'\nMemory: {df.memory_usage(deep=True).sum()/1e6:.2f} MB')Menurunkan Ukuran Kolom Float
pd.to_numeric(series, downcast='float') mengonversi float64 menjadi float32 (4 byte, bukan 8 byte) jika presisi memungkinkan. float32 memiliki sekitar 7 digit desimal presisi, sedangkan float64 memiliki 15 digit. Untuk sebagian besar tugas analitik (persentase, harga, fitur yang dinormalisasi), presisi float32 sudah memadai. Untuk komputasi ilmiah yang memerlukan presisi tinggi, tetap gunakan float64. Mengurangi separuh presisi float berarti mengurangi separuh penggunaan memori dan meningkatkan kinerja cache.
import pandas as pd
import numpy as np
np.random.seed(0)
df = pd.DataFrame({'lat': np.random.uniform(-90, 90, 1000000),
'lon': np.random.uniform(-180, 180, 1000000),
'temp': np.random.uniform(-40, 50, 1000000)})
print('Before:', df.dtypes.unique())
print(f'Memory: {df.memory_usage(deep=True).sum()/1e6:.1f} MB')
for col in df.select_dtypes('float64').columns:
df[col] = pd.to_numeric(df[col], downcast='float')
print('After:', df.dtypes.unique())
print(f'Memory: {df.memory_usage(deep=True).sum()/1e6:.1f} MB')Tipe Data Kategorikal
dtype Kategorikal memberikan penghematan memori terbesar untuk kolom string yang memiliki banyak nilai berulang. Alih-alih menyimpan string yang sama (misalnya 'Electronics') ribuan kali, Pandas menyimpan kamus berisi nilai unik serta kode integer ringkas untuk setiap baris. Kolom dengan 1 juta baris dan hanya 50 kategori unik berkurang dari sekitar 50 MB (dtype object) menjadi sekitar 1 MB (Kategorikal) — pengurangan penggunaan memori sebesar 50 kali.
import pandas as pd
import numpy as np
np.random.seed(0)
categories = ['Electronics', 'Clothing', 'Books', 'Food', 'Furniture',
'Sports', 'Toys', 'Health', 'Garden', 'Automotive']
df = pd.DataFrame({'product_cat': np.random.choice(categories, 1000000)})
mem_before = df.memory_usage(deep=True).sum()
df['product_cat'] = df['product_cat'].astype('category')
mem_after = df.memory_usage(deep=True).sum()
print(f'Object dtype: {mem_before/1e6:.1f} MB')
print(f'Categorical: {mem_after/1e6:.2f} MB')
print(f'Reduction: {mem_before/mem_after:.0f}x')Kapan Kategorikal Menghemat Memori
dtype Kategorikal hanya menghemat memori jika kolom memiliki jauh lebih sedikit nilai unik daripada jumlah total baris. Titik impasnya berada saat rasio nilai unik terhadap total baris (kardinalitas) di atas sekitar 50%: jika setiap baris memiliki string unik, Kategorikal justru menggunakan lebih banyak memori daripada dtype object karena menyimpan array kode dan array kategori. Selalu periksa df['col'].nunique() / len(df) sebelum melakukan konversi — rasio di bawah 0,5 (dan idealnya di bawah 0,05) berarti Kategorikal akan membantu.
import pandas as pd
import numpy as np
def memory_gain(df, col):
n = len(df)
n_unique = df[col].nunique()
ratio = n_unique / n
mem_obj = df[col].memory_usage(deep=True)
df2 = df.copy()
df2[col] = df2[col].astype('category')
mem_cat = df2[col].memory_usage(deep=True)
print(f'{col}: {n_unique} unique / {n} total (ratio={ratio:.3f})')
print(f' Object: {mem_obj/1e6:.2f} MB → Categorical: {mem_cat/1e6:.2f} MB')
print(f' {"Saves" if mem_cat < mem_obj else "Wastes"} {abs(mem_obj-mem_cat)/1e6:.2f} MB')
np.random.seed(0)
df = pd.DataFrame({
'low_card': np.random.choice(['A','B','C'], 500000), # low cardinality
'high_card': [f'id_{i}' for i in range(500000)] # high cardinality
})
memory_gain(df, 'low_card')
memory_gain(df, 'high_card')Kategorikal Meningkatkan Kinerja GroupBy
Selain menghemat memori, dtype Kategorikal juga mempercepat operasi groupby karena Pandas dapat langsung menggunakan kode integer, bukan melakukan hashing pada string untuk menemukan batas grup. Untuk DataFrame dengan jutaan baris yang dikelompokkan berdasarkan kolom string berkardinalitas rendah (seperti wilayah, kategori produk, atau status), mengonversi kolom tersebut menjadi Kategorikal sebelum groupby dapat menghasilkan peningkatan kecepatan 2–5 kali.
import pandas as pd
import numpy as np
import timeit
np.random.seed(0)
df = pd.DataFrame({
'region': np.random.choice(['North','South','East','West'], 1000000),
'sales': np.random.randn(1000000)
})
# Object dtype groupby
t1 = timeit.timeit(lambda: df.groupby('region')['sales'].mean(), number=50)
# Categorical dtype groupby
df2 = df.copy()
df2['region'] = df2['region'].astype('category')
t2 = timeit.timeit(lambda: df2.groupby('region')['sales'].mean(), number=50)
print(f'Object dtype groupby: {t1/50*1000:.2f} ms')
print(f'Categorical groupby: {t2/50*1000:.2f} ms')
print(f'Speedup: {t1/t2:.1f}x')Menggunakan dtype boolean untuk Kolom Penanda
Kolom biner (True/False, 0/1, ya/tidak) sering disimpan sebagai object atau int64. Mengonversinya menjadi dtype bool hanya menggunakan 1 byte per nilai (dibandingkan 8 byte untuk int64 atau lebih dari 50 byte untuk string 'yes'/'no'). Gunakan astype(bool) setelah memastikan kolom hanya berisi nilai 0/1 atau True/False. Kolom boolean juga memungkinkan pemfilteran yang lebih cepat karena Pandas dapat menggunakan operasi bitwise secara internal.
import pandas as pd
import numpy as np
np.random.seed(0)
df = pd.DataFrame({
'is_premium': np.random.choice([0, 1], 1000000).astype('int64'),
'has_discount': np.random.choice(['yes', 'no'], 1000000)
})
print('Before:')
print(df.dtypes)
print(f'Memory: {df.memory_usage(deep=True).sum()/1e6:.1f} MB')
df['is_premium'] = df['is_premium'].astype(bool)
df['has_discount'] = df['has_discount'].map({'yes': True, 'no': False}).astype(bool)
print('\nAfter:')
print(df.dtypes)
print(f'Memory: {df.memory_usage(deep=True).sum()/1e6:.2f} MB')Mengotomatiskan Optimisasi Tipe
Tulis fungsi optimise_dtypes(df) yang dapat digunakan kembali untuk menerapkan semua optimasi secara otomatis: mengubah tipe bilangan bulat ke tipe yang lebih kecil, mengubah tipe bilangan pecahan ke tipe yang lebih kecil, mengonversi objek dengan kardinalitas rendah menjadi Categorical, dan mengonversi bilangan bulat 0/1 menjadi bool. Jalankan fungsi ini saat memuat data untuk meminimalkan penggunaan memori sejak awal. Dengan demikian, setiap anggota tim yang memuat dataset yang sama akan mendapatkan versi yang telah dioptimalkan tanpa harus mengingat untuk menerapkan setiap langkah secara manual.
import pandas as pd
import numpy as np
def optimise_dtypes(df, cat_threshold=0.5):
'''Reduce DataFrame memory by choosing smaller dtypes.'''
for col in df.columns:
col_type = df[col].dtype
if col_type == 'int64':
df[col] = pd.to_numeric(df[col], downcast='integer')
elif col_type == 'float64':
df[col] = pd.to_numeric(df[col], downcast='float')
elif col_type == 'object':
cardinality = df[col].nunique() / len(df)
if cardinality < cat_threshold:
df[col] = df[col].astype('category')
return df
# Test
np.random.seed(0)
df = pd.DataFrame({'a': np.random.randint(0,100,500000),
'b': np.random.randn(500000),
'c': np.random.choice(['X','Y','Z'],500000)})
before = df.memory_usage(deep=True).sum()
df = optimise_dtypes(df)
after = df.memory_usage(deep=True).sum()
print(f'Before: {before/1e6:.2f} MB → After: {after/1e6:.2f} MB ({before/after:.1f}x reduction)')Tipe Bilangan Bulat Tak Bertanda untuk Data Non-Negatif
Jika suatu kolom hanya berisi bilangan bulat non-negatif (seperti ID, jumlah, atau kuantitas), gunakan tipe bilangan bulat tak bertanda: uint8 (0–255), uint16 (0–65535), uint32 (0–4 miliar), atau uint64. Tipe tak bertanda memiliki ukuran byte yang sama dengan tipe bertanda, tetapi dapat menyimpan nilai positif hingga dua kali lebih besar. Misalnya, ID produk yang berkisar dari 0 hingga 60.000 dapat disimpan dalam uint16 (2 byte), bukan int32 (4 byte). Gunakan astype('uint16') setelah memastikan kolom tersebut tidak memiliki nilai negatif.
import pandas as pd
import numpy as np
np.random.seed(0)
df = pd.DataFrame({
'product_id': np.random.randint(0, 50000, 1000000).astype('int64'),
'quantity': np.random.randint(0, 255, 1000000).astype('int64')
})
print('Before (int64):', df.memory_usage(deep=True).sum() / 1e6, 'MB')
# product_id fits in uint16 (0-65535)
df['product_id'] = df['product_id'].astype('uint16')
# quantity fits in uint8 (0-255)
df['quantity'] = df['quantity'].astype('uint8')
print('After (uint16+uint8):', df.memory_usage(deep=True).sum() / 1e6, 'MB')
print('\nDtypes:', df.dtypes.to_dict())Memeriksa Memori Setelah Setiap Langkah Optimasi
Terapkan optimasi satu per satu dan periksa memori setelah setiap langkah. Dengan begitu, Anda dapat melihat secara tepat kontribusi setiap teknik. DataFrame besar yang umum mungkin berkurang dari 2 GB (semua tipe data bawaan) menjadi 600 MB (pengubahan tipe bilangan bulat ke tipe yang lebih kecil), lalu menjadi 300 MB (pengubahan tipe bilangan pecahan ke tipe yang lebih kecil), dan akhirnya menjadi 200 MB (Categorical untuk kolom string). Mendokumentasikan rincian ini membantu menjelaskan alasan kompleksitas tambahan kepada anggota tim yang melihat tipe data yang belum familiar di basis kode.
import pandas as pd
import numpy as np
np.random.seed(0)
df = pd.DataFrame({
'user_id': np.random.randint(0, 99999, 1000000).astype('int64'),
'age': np.random.randint(18, 80, 1000000).astype('int64'),
'revenue': np.random.uniform(0, 5000, 1000000).astype('float64'),
'country': np.random.choice(['US','UK','DE','FR','JP'], 1000000),
'tier': np.random.choice(['free','basic','pro','enterprise'], 1000000)
})
def mem_mb(df):
return df.memory_usage(deep=True).sum() / 1e6
print(f'Start: {mem_mb(df):.1f} MB')
for c in ['user_id','age']:
df[c] = pd.to_numeric(df[c], downcast='integer')
print(f'After int downcast: {mem_mb(df):.1f} MB')
df['revenue'] = pd.to_numeric(df['revenue'], downcast='float')
print(f'After float downcast: {mem_mb(df):.1f} MB')
for c in ['country','tier']:
df[c] = df[c].astype('category')
print(f'After Categorical: {mem_mb(df):.1f} MB')Menyimpan dan Memuat Ulang Tipe yang Dioptimalkan
Tipe data yang telah dioptimalkan akan hilang jika Anda menyimpan data ke CSV (karena semuanya dikonversi kembali menjadi teks). Untuk mempertahankan tipe data, simpan dalam format Parquet dengan df.to_parquet('file.parquet') — Parquet mempertahankan tipe int32, float32, dan Categorical. Saat dimuat ulang dengan pd.read_parquet, DataFrame memiliki tipe yang sama dan hemat memori tanpa perlu menjalankan kembali fungsi optimasi. Parquet juga memuat data jauh lebih cepat daripada CSV untuk file besar.
import pandas as pd
import numpy as np
np.random.seed(0)
df = pd.DataFrame({
'age': np.random.randint(18, 80, 100000).astype('int8'), # already optimised
'score': np.random.randn(100000).astype('float32'),
'tier': pd.Categorical(np.random.choice(['free','pro'], 100000))
})
print('Dtypes:', df.dtypes.to_dict())
# Save to Parquet (preserves dtypes)
df.to_parquet('/tmp/optimised.parquet', index=False)
# Reload — dtypes preserved!
df_loaded = pd.read_parquet('/tmp/optimised.parquet')
print('\nLoaded dtypes:', df_loaded.dtypes.to_dict())
print(f'Memory: {df_loaded.memory_usage(deep=True).sum()/1e6:.2f} MB')Pemeriksaan Singkat
Uji pemahaman Anda tentang tipe data yang hemat memori dari pelajaran ini.
Rangkuman Pelajaran
Dalam pelajaran ini Anda mempelajari bahwa: pd.to_numeric(downcast='integer') mengurangi ukuran kolom bilangan bulat dari 8 byte menjadi 1–4 byte, pd.to_numeric(downcast='float') mengurangi separuh penggunaan memori bilangan pecahan, tipe data Categorical mengurangi ukuran kolom string dengan kardinalitas rendah hingga 50 kali sekaligus mempercepat groupby, dan format Parquet mempertahankan tipe data yang dioptimalkan saat file disimpan dan dimuat ulang. Selanjutnya kita akan mempelajari pembacaan secara berpotongan — memproses file yang ukurannya melebihi RAM yang tersedia.
Belajar Python dengan tutor AI — gratis
Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.
- Kursus
- 30
- Pelajaran
- 120
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Tipe Data Efisien untuk Mengurangi Memori” gratis?
Ya — teks lengkap “Tipe Data Efisien untuk Mengurangi Memori” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Pandas & NumPy Academy, upgrade ke CoddyKit PRO. Kursus Pandas & NumPy Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Tipe Data Efisien untuk Mengurangi Memori”?
Turunkan tipe kolom numerik menjadi int32/float32 dan konversikan kolom string menjadi Categorical untuk mengurangi memori DataFrame hingga 70%. Kamu berlatih Pandas & NumPy Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Pandas & NumPy Academy?
Tidak diperlukan pengalaman sebelumnya. Pandas & NumPy Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.
Berapa lama pelajaran “Tipe Data Efisien untuk Mengurangi Memori” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Pandas & NumPy Academy ini?
Ya. Setiap pelajaran Pandas & NumPy Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Pemrofilan dengan timeit dan memory_profiler
- Menghindari iterrows dan Perulangan Python
- Tipe Data Efisien untuk Mengurangi Memori
- Membaca File Besar dalam Potongan