Bellek Azaltma için Verimli Veri Türleri
DataFrame bellek kullanımını %70'e kadar azaltmak için sayısal sütunları int32/float32 türüne küçültün ve dize sütunlarını Categorical türüne dönüştürün.
Bellek Azaltma için Verimli Veri Türleri, CoddyKit'te ücretsiz bir Pandas & NumPy Academy dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Pandas & NumPy Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Pandas & NumPy Academy kursu toplamda 4 dersten oluşur.
Veri Türleri Performansı Neden Etkiler
Pandas'ta her sütunun, değerlerin bellekte nasıl saklanacağını ve işlemlerin ne kadar hızlı çalışacağını belirleyen bir dtype'ı (veri türü) vardır. Pandas, verileri yüklerken varsayılan olarak geniş türleri kullanır: int64 (değer başına 8 bayt), float64 (8 bayt) ve object (değişken boyutlu, dize başına çoğu zaman 50-200 bayt). Milyonlarca satır söz konusu olduğunda daha küçük türleri seçmek, belleği %50-80 oranında azaltabilir ve önbelleğin daha iyi kullanılmasını sağlayarak işlemleri 2-5 kat hızlandırabilir.
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')Tamsayı Sütunlarını Küçültme
Bir sütundaki tamsayı değerleri daha küçük bir aralığa sığıyorsa, sütunu int64'ten daha küçük bir tamsayı türüne küçültün. pd.to_numeric(series, downcast='integer'), tüm değerleri barındırabilecek en küçük tamsayı türünü otomatik olarak seçer: int8 (–128 ile 127, 1 bayt), int16 (–32768 ile 32767, 2 bayt), int32 (±2 milyar, 4 bayt) veya gerekirse int64 olarak kalır. int8 sütunu, int64'e göre 8 kat daha az bellek kullanır.
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')Ondalık Sütunlarını Küçültme
pd.to_numeric(series, downcast='float'), hassasiyetin elverdiği yerlerde float64 türünü float32 türüne dönüştürür (8 yerine 4 bayt). float32, float64'teki 15 basamağa kıyasla yaklaşık 7 ondalık basamak hassasiyetine sahiptir. Çoğu analitik görev için (yüzdeler, fiyatlar, normalleştirilmiş özellikler) float32 hassasiyeti yeterlidir. Yüksek hassasiyet gerektiren bilimsel hesaplamalarda float64 kullanmaya devam edin. Ondalık hassasiyetini yarıya indirmek belleği yarıya indirir ve önbellek performansını artırır.
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')Categorical Veri Türü
Categorical dtype, tekrarlanan değerlere sahip dize sütunlarında belleği en çok azaltan seçenektir. Aynı dizeyi (örneğin 'Electronics') binlerce kez saklamak yerine Pandas, benzersiz değerlerden oluşan bir sözlük ile her satır için küçük bir tamsayı kodu saklar. 1 milyon satırlı ve yalnızca 50 benzersiz kategorili bir sütun, yaklaşık 50 MB'tan (object dtype) yaklaşık 1 MB'a (Categorical) iner; bu, bellekte 50 kat azalma demektir.
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')Categorical Ne Zaman Bellek Kazandırır
Categorical dtype yalnızca sütunda toplam satır sayısından çok daha az sayıda benzersiz değer bulunduğunda bellek kazandırır. Başabaş noktası, benzersiz değerlerin toplam satırlara oranı (kardinalite) yaklaşık %50'nin üzerindeyken oluşur: her satırda benzersiz bir dize varsa Categorical, hem kod dizisini hem de kategoriler dizisini sakladığı için aslında object dtype'tan daha fazla bellek kullanır. Dönüştürmeden önce her zaman df['col'].nunique() / len(df) değerini kontrol edin — 0,5'in altında (ideal olarak 0,05'in altında) bir oran Categorical'ın yarar sağlayacağı anlamına gelir.
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')Categorical, GroupBy Performansını Artırır
Bellek tasarrufunun yanı sıra Categorical dtype, groupby işlemlerini de hızlandırır; çünkü Pandas grup sınırlarını bulmak için dizeleri özetlemek yerine doğrudan tamsayı kodlarını kullanabilir. Bölge, ürün kategorisi veya durum gibi düşük kardinaliteli dize sütunlarına göre gruplanmış milyonlarca satırlı DataFrame nesnelerinde, groupby işleminden önce bu sütunları Categorical'a dönüştürmek 2-5 kat hızlanma sağlayabilir.
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')Bayrak Sütunları için boolean dtype Kullanma
İkili sütunlar (True/False, 0/1, yes/no) çoğu zaman object veya int64 olarak saklanır. Bunları bool dtype'a dönüştürmek, değer başına yalnızca 1 bayt kullanır (int64 için 8 bayt veya 'yes'/'no' dizeleri için 50'den fazla bayta kıyasla). Sütunun yalnızca 0/1 ya da True/False değerlerini içerdiğinden emin olduktan sonra astype(bool) kullanın. Boolean sütunları, Pandas'ın dahili olarak bitsel işlemler kullanabilmesi sayesinde daha hızlı filtrelemeyi de mümkün kılar.
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')Tür İyileştirmesini Otomatikleştirme
Tüm iyileştirmeleri otomatik olarak uygulayan yeniden kullanılabilir bir optimise_dtypes(df) işlevi yazın: tamsayıları küçültsün, ondalıkları küçültsün, düşük kardinaliteli object türlerini Categorical'a dönüştürsün ve 0/1 tamsayılarını bool'a dönüştürsün. Belleği en baştan en aza indirmek için bu işlevi veriler yüklenirken çalıştırın. Böylece her ekip üyesi, her adımı elle uygulamayı hatırlamak zorunda kalmadan aynı veri kümesinin iyileştirilmiş sürümünü yükleyebilir.
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)')Negatif Olmayan Veriler için İşaretsiz Tamsayı Türleri
Bir sütun yalnızca negatif olmayan tamsayılar içeriyorsa (ID'ler, sayımlar veya miktarlar gibi), işaretsiz tamsayı türlerini kullanın: uint8 (0–255), uint16 (0–65535), uint32 (0–4 milyar) veya uint64. İşaretsiz türler, işaretli karşılıklarıyla aynı bayt boyutuna sahiptir; ancak pozitif aralıkta iki kata kadar daha büyük değerleri saklayabilir. Örneğin, 0 ile 60.000 arasında değer alan bir ürün ID'si, 4 baytlık int32 yerine 2 baytlık uint16 türüne sığar. Sütunda negatif değer bulunmadığını doğruladıktan sonra astype('uint16') kullanın.
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())Her İyileştirme Adımından Sonra Belleği Kontrol Etme
İyileştirmeleri tek tek uygulayın ve her adımdan sonra belleği kontrol edin. Böylece her tekniğin ne kadar katkı sağladığını tam olarak görebilirsiniz. Tipik bir büyük DataFrame, tüm varsayılan dtype'larla 2 GB'tan tamsayıların küçültülmesiyle 600 MB'a, ardından ondalıkların küçültülmesiyle 300 MB'a ve son olarak dize sütunlarında Categorical kullanılmasıyla 200 MB'a düşebilir. Bu dağılımı belgelemek, kod tabanında alışılmadık dtype'lar gören ekip üyelerine ek karmaşıklığın gerekçesini açıklamaya yardımcı olur.
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')İyileştirilmiş Türleri Kaydetme ve Yeniden Yükleme
CSV'ye kaydederseniz iyileştirilmiş dtype'lar kaybolur (her şey yeniden metne dönüştürülür). dtype'ları korumak için df.to_parquet('file.parquet') ile Parquet biçiminde kaydedin — Parquet, int32, float32 ve Categorical türlerini korur. pd.read_parquet ile yeniden yüklendiğinde DataFrame, iyileştirme işlevini yeniden çalıştırmadan aynı bellek verimli türlere sahip olur. Parquet ayrıca büyük dosyaları CSV'den önemli ölçüde daha hızlı yükler.
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')Hızlı Kontrol
Bu derste öğrendiğiniz bellek verimli veri türleri konusunu ne kadar anladığınızı sınayın.
Ders Özeti
Bu derste şunları öğrendiniz: pd.to_numeric(downcast='integer'), tamsayı sütunlarını 8 bayttan 1-4 bayta düşürür; pd.to_numeric(downcast='float'), ondalık sayıların bellek kullanımını yarıya indirir; Categorical dtype, düşük kardinaliteli dize sütunlarını 50 kata kadar küçültürken groupby işlemini de hızlandırır ve Parquet biçimi, dosya kaydetme/yükleme döngüleri boyunca iyileştirilmiş dtype'ları korur. Sırada, kullanılabilir RAM'i aşan dosyaları işlemeyi sağlayan parça parça okumayı ele alacağız.
Sıkça Sorulan Sorular
“Bellek Azaltma için Verimli Veri Türleri” dersi ücretsiz mi?
Evet — “Bellek Azaltma için Verimli Veri Türleri” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Pandas & NumPy Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Pandas & NumPy Academy kursu toplamda 4 dersten oluşur.
“Bellek Azaltma için Verimli Veri Türleri” dersinde ne öğreneceğim?
DataFrame bellek kullanımını %70'e kadar azaltmak için sayısal sütunları int32/float32 türüne küçültün ve dize sütunlarını Categorical türüne dönüştürün. Pandas & NumPy Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
Pandas & NumPy Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te Pandas & NumPy Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.
“Bellek Azaltma için Verimli Veri Türleri” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu Pandas & NumPy Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her Pandas & NumPy Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- timeit ve memory_profiler ile Profilleme
- iterrows ve Python Döngülerinden Kaçınma
- Bellek Azaltma için Verimli Veri Türleri
- Büyük Dosyaları Parçalı Okuma