Pandas DataFrame'larni xotiradan foydalanish va ishlash samaradorligi bo'yicha optimallashtirish bo'yicha to'liq qo'llanma, ma'lumot turlari, indekslash va ilg'or usullarni qamrab oladi.
Pandas DataFrame'ni optimallashtirish: Xotiradan foydalanish va ishlash samaradorligini sozlash
Pandas - bu ma'lumotlarni manipulyatsiya qilish va tahlil qilish uchun kuchli Python kutubxonasi. Biroq, katta hajmdagi ma'lumotlar to'plamlari bilan ishlaganda, Pandas DataFrame'lari sezilarli miqdorda xotira egallashi va sekin ishlashi mumkin. Ushbu maqola Pandas DataFrame'larini xotiradan foydalanish va ishlash samaradorligi bo'yicha optimallashtirish uchun keng qamrovli qo'llanma taqdim etadi, bu sizga kattaroq ma'lumotlar to'plamlarini samaraliroq qayta ishlash imkonini beradi.
Pandas DataFrame'larida xotiradan foydalanishni tushunish
Optimallashtirish usullariga sho'ng'ishdan oldin, Pandas DataFrame'larining ma'lumotlarni xotirada qanday saqlashini tushunish juda muhimdir. DataFrame'dagi har bir ustun o'z qiymatlarini saqlash uchun zarur bo'lgan xotira miqdorini belgilaydigan o'ziga xos ma'lumot turiga ega. Umumiy ma'lumot turlariga quyidagilar kiradi:
- int64: 64 bitli butun sonlar (butun sonlar uchun standart)
- float64: 64 bitli o'nli kasr sonlar (o'nli kasr sonlar uchun standart)
- object: Python obyektlari (satrlar va aralash ma'lumot turlari uchun ishlatiladi)
- category: Kategorik ma'lumotlar (takrorlanuvchi qiymatlar uchun samarali)
- bool: Mantiqiy qiymatlar (True/False)
- datetime64: Sana va vaqt qiymatlari
object ma'lumot turi ko'pincha eng ko'p xotira talab qiladi, chunki u Python obyektlariga havolalarni saqlaydi, bu esa butun sonlar yoki o'nli kasrlar kabi sodda ma'lumot turlaridan ancha katta bo'lishi mumkin. Qisqa satrlar ham, object sifatida saqlansa, keragidan ancha ko'p xotira egallaydi. Xuddi shunday, int32 yetarli bo'lgan joyda int64 dan foydalanish xotirani isrof qilishga olib keladi.
Misol: DataFrame xotirasidan foydalanishni tekshirish
DataFrame'ning xotiradan foydalanishini tekshirish uchun memory_usage() metodidan foydalanishingiz mumkin:
import pandas as pd
import numpy as np
data = {
'col1': np.random.randint(0, 1000, 100000),
'col2': np.random.rand(100000),
'col3': ['A', 'B', 'C'] * (100000 // 3 + 1)[:100000],
'col4': ['This is a long string'] * 100000
}
df = pd.DataFrame(data)
memory_usage = df.memory_usage(deep=True)
print(memory_usage)
print(df.dtypes)
deep=True argumenti obyektlarning (masalan, satrlar) xotiradan foydalanishi to'g'ri hisoblanishini ta'minlaydi. deep=True bo'lmasa, u faqat havolalar uchun xotirani hisoblaydi, asl ma'lumotlarning o'zini emas.
Ma'lumotlar turlarini optimallashtirish
Xotiradan foydalanishni kamaytirishning eng samarali usullaridan biri bu DataFrame ustunlari uchun eng mos ma'lumot turlarini tanlashdir. Mana bir nechta keng tarqalgan usullar:
1. Raqamli ma'lumotlar turlarini kichraytirish
Agar sizning butun sonli yoki o'nli kasrli ustunlaringiz 64 bitli aniqlikning to'liq diapazonini talab qilmasa, ularni int32, int16, float32 yoki float16 kabi kichikroq ma'lumot turlariga o'tkazishingiz mumkin. Bu, ayniqsa, katta ma'lumotlar to'plamlari uchun xotiradan foydalanishni sezilarli darajada kamaytirishi mumkin.
Misol: Yoshni ifodalovchi ustunni ko'rib chiqing, uning qiymati 120 dan oshishi dargumon. Buni int64 sifatida saqlash isrofgarchilikdir; int8 (diapazon -128 dan 127 gacha) ancha mos keladi.
def downcast_numeric(df):
"""Downcasts numeric columns to the smallest possible data type."""
for col in df.columns:
if pd.api.types.is_integer_dtype(df[col]):
df[col] = pd.to_numeric(df[col], downcast='integer')
elif pd.api.types.is_float_dtype(df[col]):
df[col] = pd.to_numeric(df[col], downcast='float')
return df
df = downcast_numeric(df.copy())
print(df.memory_usage(deep=True))
print(df.dtypes)
downcast argumenti bilan pd.to_numeric() funksiyasi ustundagi qiymatlarni ifodalay oladigan eng kichik mumkin bo'lgan ma'lumot turini avtomatik tanlash uchun ishlatiladi. copy() asl DataFrame'ni o'zgartirishdan saqlaydi. Ma'lumotni yo'qotmaslik uchun kichraytirishdan oldin har doim ma'lumotlaringizdagi qiymatlar diapazonini tekshiring.
2. Kategorik ma'lumotlar turlaridan foydalanish
Agar ustun cheklangan miqdordagi noyob qiymatlarni o'z ichiga olsa, uni category ma'lumot turiga o'zgartirishingiz mumkin. Kategorik ma'lumot turlari har bir noyob qiymatni faqat bir marta saqlaydi va keyin ustundagi qiymatlarni ifodalash uchun butun sonli kodlardan foydalanadi. Bu, ayniqsa, takrorlanadigan qiymatlar ulushi yuqori bo'lgan ustunlar uchun xotiradan foydalanishni sezilarli darajada kamaytirishi mumkin.
Misol: Mamlakat kodlarini ifodalovchi ustunni ko'rib chiqing. Agar siz cheklangan mamlakatlar to'plami (masalan, faqat Yevropa Ittifoqi mamlakatlari) bilan ishlayotgan bo'lsangiz, buni kategoriya sifatida saqlash satrlar sifatida saqlashdan ko'ra ancha samaraliroq bo'ladi.
def optimize_categories(df):
"""Converts object columns with low cardinality to categorical type."""
for col in df.columns:
if df[col].dtype == 'object':
num_unique_values = len(df[col].unique())
num_total_values = len(df[col])
if num_unique_values / num_total_values < 0.5:
df[col] = df[col].astype('category')
return df
df = optimize_categories(df.copy())
print(df.memory_usage(deep=True))
print(df.dtypes)
Ushbu kod obyekt ustunidagi noyob qiymatlar soni umumiy qiymatlar sonining 50% dan kam yoki yo'qligini tekshiradi. Agar shunday bo'lsa, u ustunni kategorik ma'lumot turiga o'zgartiradi. 50% chegarasi ixtiyoriy bo'lib, ma'lumotlaringizning o'ziga xos xususiyatlariga qarab sozlanishi mumkin. Ushbu yondashuv ustun ko'p takrorlanadigan qiymatlarni o'z ichiga olganda eng foydalidir.
3. Satrlar uchun obyekt ma'lumot turlaridan qochish
Yuqorida aytib o'tilganidek, object ma'lumot turi ko'pincha eng ko'p xotira talab qiladi, ayniqsa satrlarni saqlash uchun ishlatilganda. Iloji bo'lsa, satr ustunlari uchun object ma'lumot turlaridan foydalanishdan qochishga harakat qiling. Kardinalligi (noyob qiymatlar soni) past bo'lgan satrlar uchun kategorik turlar afzalroq. Agar kardinallik yuqori bo'lsa, satrlarni raqamli kodlar bilan ifodalash mumkinmi yoki satrli ma'lumotlardan umuman qochish mumkinmi, deb o'ylab ko'ring.
Agar ustun ustida satr amallarini bajarishingiz kerak bo'lsa, uni obyekt turi sifatida saqlashingiz kerak bo'lishi mumkin, lekin bu amallarni oldindan bajarib, so'ngra samaraliroq turga o'zgartirish mumkinmi, deb o'ylab ko'ring.
4. Sana va vaqt ma'lumotlari
Sana va vaqt ma'lumotlari uchun datetime64 ma'lumot turidan foydalaning. Ruxsat aniqligi mos ekanligiga ishonch hosil qiling (nanosekund aniqligi keraksiz bo'lishi mumkin). Pandas vaqt qatorlari ma'lumotlarini juda samarali boshqaradi.
DataFrame amallarini optimallashtirish
Ma'lumotlar turlarini optimallashtirishdan tashqari, siz Pandas DataFrame'larida bajaradigan amallarni optimallashtirish orqali ham ularning ishlash samaradorligini oshirishingiz mumkin. Mana bir nechta keng tarqalgan usullar:
1. Vektorlashtirish
Vektorlashtirish - bu alohida elementlar ustida iteratsiya qilish o'rniga, butun massivlar yoki ustunlar ustida bir vaqtning o'zida amallarni bajarish jarayonidir. Pandas vektorlashtirilgan amallar uchun yuqori darajada optimallashtirilgan, shuning uchun ulardan foydalanish ishlash samaradorligini sezilarli darajada oshirishi mumkin. Iloji boricha ochiq sikllardan qoching. Pandas'ning o'rnatilgan funksiyalari odatda ekvivalent Python sikllaridan ancha tezroq ishlaydi.
Misol: Har bir qiymatning kvadratini hisoblash uchun ustun bo'ylab iteratsiya qilish o'rniga, ** operatoridan foydalaning:
# Samarasiz (sikl yordamida)
import time
start_time = time.time()
results = []
for value in df['col2']:
results.append(value ** 2)
df['col2_squared_loop'] = results
end_time = time.time()
print(f"Sikl vaqti: {end_time - start_time:.4f} soniya")
# Samarali (vektorlashtirish yordamida)
start_time = time.time()
df['col2_squared_vectorized'] = df['col2'] ** 2
end_time = time.time()
print(f"Vektorlashtirilgan vaqt: {end_time - start_time:.4f} soniya")
Vektorlashtirilgan yondashuv odatda siklga asoslangan yondashuvdan bir necha barobar tezroq bo'ladi.
2. `apply()` metodidan ehtiyotkorlik bilan foydalanish
apply() metodi DataFrame'ning har bir qatori yoki ustuniga funksiya qo'llash imkonini beradi. Biroq, u odatda vektorlashtirilgan amallardan sekinroq ishlaydi, chunki u har bir element uchun Python funksiyasini chaqirishni o'z ichiga oladi. apply() metodidan faqat vektorlashtirilgan amallar mumkin bo'lmaganda foydalaning.
Agar apply() dan foydalanishingiz shart bo'lsa, qo'llayotgan funksiyangizni iloji boricha vektorlashtirishga harakat qiling. Ishlash samaradorligini sezilarli darajada oshirish uchun funksiyani mashina kodiga kompilyatsiya qilish uchun Numba'ning jit dekoratoridan foydalanishni o'ylab ko'ring.
from numba import jit
@jit(nopython=True)
def my_function(x):
return x * 2 # Misol funksiya
df['col2_applied'] = df['col2'].apply(my_function)
3. Ustunlarni samarali tanlash
DataFrame'dan ustunlar to'plamini tanlashda optimal ishlash uchun quyidagi usullardan foydalaning:
- To'g'ridan-to'g'ri ustun tanlash:
df[['col1', 'col2']](bir nechta ustunni tanlash uchun eng tezkor) - Mantiqiy indekslash:
df.loc[:, [True if col.startswith('col') else False for col in df.columns]](shart asosida ustunlarni tanlash uchun foydali)
Ustunlarni tanlash uchun df.filter() metodini muntazam ifodalar bilan ishlatishdan qoching, chunki u boshqa usullarga qaraganda sekinroq bo'lishi mumkin.
4. Birlashtirish (Joins) va qo'shish (Merges) operatsiyalarini optimallashtirish
DataFrame'larni birlashtirish va qo'shish, ayniqsa katta ma'lumotlar to'plamlari uchun, hisoblash jihatidan qimmat bo'lishi mumkin. Birlashtirish va qo'shishni optimallashtirish uchun ba'zi maslahatlar:
- Mos birlashtirish kalitlaridan foydalaning: Birlashtirish kalitlari bir xil ma'lumot turiga ega va indekslangan ekanligiga ishonch hosil qiling.
- Birlashtirish turini belgilang: Talablaringizga qarab mos birlashtirish turidan (masalan,
inner,left,right,outer) foydalaning. Ichki (inner) birlashtirish odatda tashqi (outer) birlashtirishdan tezroq bo'ladi. join()o'rnigamerge()dan foydalaning:merge()funksiyasi ko'p qirrali va ko'pinchajoin()metodidan tezroq ishlaydi.
Misol:
df1 = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'value1': [1, 2, 3, 4]})
df2 = pd.DataFrame({'key': ['B', 'D', 'E', 'F'], 'value2': [5, 6, 7, 8]})
# Samarali ichki birlashtirish
df_merged = pd.merge(df1, df2, on='key', how='inner')
print(df_merged)
5. DataFrame'larni keraksiz nusxalashdan qochish
Ko'pgina Pandas amallari DataFrame'larning nusxalarini yaratadi, bu esa xotira va vaqt talab qilishi mumkin. Keraksiz nusxalashdan qochish uchun, mavjud bo'lganda inplace=True argumentidan foydalaning yoki amal natijasini asl DataFrame'ga qayta tayinlang. inplace=True bilan juda ehtiyot bo'ling, chunki u xatoliklarni yashirishi va disk raskadrovka qilishni qiyinlashtirishi mumkin. Biroz sekinroq bo'lsa ham, qayta tayinlash ko'pincha xavfsizroqdir.
Misol:
# Samarasiz (nusxa yaratadi)
df_filtered = df[df['col1'] > 500]
# Samarali (asl DataFrame'ni joyida o'zgartiradi - EHTIYOT BO'LING)
df.drop(df[df['col1'] <= 500].index, inplace=True)
#XAVFSIZROQ - qayta tayinlaydi, inplace'dan qochadi
df = df[df['col1'] > 500]
6. Bo'laklarga bo'lish va iteratsiya qilish
Xotiraga sig'maydigan juda katta ma'lumotlar to'plamlari uchun ma'lumotlarni bo'laklarga bo'lib qayta ishlashni ko'rib chiqing. Fayllardan ma'lumotlarni o'qishda chunksize parametrini ishlating. Bo'laklar bo'ylab iteratsiya qiling va tahlilingizni har bir bo'lakda alohida bajaring. Bu tahlilning to'g'ri bo'lishini ta'minlash uchun ehtiyotkorlik bilan rejalashtirishni talab qiladi, chunki ba'zi amallar butun ma'lumotlar to'plamini bir vaqtning o'zida qayta ishlashni talab qiladi.
# CSV faylni bo'laklarga bo'lib o'qish
for chunk in pd.read_csv('large_data.csv', chunksize=100000):
# Har bir bo'lakni qayta ishlash
print(chunk.shape)
7. Parallel qayta ishlash uchun Dask'dan foydalanish
Dask - bu Pandas bilan uzviy bog'langan parallel hisoblash kutubxonasi. U katta DataFrame'larni parallel ravishda qayta ishlash imkonini beradi, bu esa ishlash samaradorligini sezilarli darajada oshirishi mumkin. Dask DataFrame'ni kichikroq qismlarga bo'ladi va ularni bir nechta yadro yoki mashinalar bo'ylab taqsimlaydi.
import dask.dataframe as dd
# Dask DataFrame yaratish
ddf = dd.read_csv('large_data.csv')
# Dask DataFrame ustida amallarni bajarish
ddf_filtered = ddf[ddf['col1'] > 500]
# Natijani hisoblash (bu parallel hisoblashni ishga tushiradi)
result = ddf_filtered.compute()
print(result.head())
Tezroq qidiruvlar uchun indekslash
Ustunga indeks yaratish qidiruv va filtrlash amallarini sezilarli darajada tezlashtirishi mumkin. Pandas ma'lum bir qiymatga mos keladigan qatorlarni tezda topish uchun indekslardan foydalanadi.
Misol:
# 'col3' ni indeks sifatida o'rnatish
df = df.set_index('col3')
# Tezroq qidiruv
value = df.loc['A']
print(value)
# Indeksni tiklash
df = df.reset_index()
Biroq, juda ko'p indeks yaratish xotiradan foydalanishni oshirishi va yozish amallarini sekinlashtirishi mumkin. Faqat qidiruv yoki filtrlash uchun tez-tez ishlatiladigan ustunlarda indeks yarating.
Boshqa mulohazalar
- Uskunalar: Agar siz doimiy ravishda katta ma'lumotlar to'plamlari bilan ishlayotgan bo'lsangiz, uskunangizni (CPU, RAM, SSD) yangilashni o'ylab ko'ring.
- Dasturiy ta'minot: Pandas'ning eng so'nggi versiyasidan foydalanayotganingizga ishonch hosil qiling, chunki yangi versiyalarda ko'pincha ishlash samaradorligini oshiruvchi o'zgarishlar bo'ladi.
- Profil yaratish: Kodingizdagi ishlash samaradorligining zaif nuqtalarini aniqlash uchun profil yaratish vositalaridan (masalan,
cProfile,line_profiler) foydalaning. - Ma'lumotlarni saqlash formati: CSV o'rniga Parquet yoki Feather kabi samaraliroq ma'lumotlarni saqlash formatlaridan foydalanishni ko'rib chiqing. Bu formatlar ustunli va ko'pincha siqilgan bo'lib, fayl hajmini kichraytiradi va o'qish/yozish vaqtini tezlashtiradi.
Xulosa
Pandas DataFrame'larini xotiradan foydalanish va ishlash samaradorligi bo'yicha optimallashtirish katta ma'lumotlar to'plamlari bilan samarali ishlash uchun juda muhimdir. Tegishli ma'lumot turlarini tanlash, vektorlashtirilgan amallardan foydalanish va ma'lumotlaringizni samarali indekslash orqali siz xotira sarfini sezilarli darajada kamaytirishingiz va ishlash samaradorligini oshirishingiz mumkin. Ishlashdagi zaif nuqtalarni aniqlash uchun kodingizni profilini yaratishni unutmang va juda katta ma'lumotlar to'plamlari uchun bo'laklarga bo'lish yoki Dask'dan foydalanishni ko'rib chiqing. Ushbu usullarni qo'llash orqali siz ma'lumotlarni tahlil qilish va manipulyatsiya qilish uchun Pandas'ning to'liq salohiyatini ochishingiz mumkin.