Išsamus vadovas, kaip optimizuoti Pandas atminties naudojimą, apimantis duomenų tipus, skaidymą į dalis, kategorinius kintamuosius ir efektyvius metodus dideliems duomenų rinkiniams tvarkyti.
Pandas našumo optimizavimas: atminties naudojimo mažinimo įvaldymas
Pandas yra galinga Python biblioteka, skirta duomenų analizei, teikianti lanksčias duomenų struktūras ir duomenų analizės įrankius. Tačiau, dirbant su dideliais duomenų rinkiniais, atminties naudojimas gali tapti didele kliūtimi, darančia įtaką našumui ir netgi sukelti programų gedimus. Šis išsamus vadovas nagrinėja įvairius metodus, skirtus optimizuoti Pandas atminties naudojimą, leidžiančius efektyviau ir veiksmingiau tvarkyti didesnius duomenų rinkinius.
Pandas atminties naudojimo supratimas
Prieš pradedant optimizavimo metodus, labai svarbu suprasti, kaip Pandas saugo duomenis atmintyje. Pandas pirmiausia naudoja NumPy masyvus duomenims saugoti DataFrames ir Series viduje. Kiekvieno stulpelio duomenų tipas labai veikia atminties pėdsaką. Pavyzdžiui, `int64` stulpelis sunaudos dvigubai daugiau atminties nei `int32` stulpelis.
Galite patikrinti DataFrame atminties naudojimą naudodami .memory_usage() metodą:
import pandas as pd
data = {
'col1': [1, 2, 3, 4, 5],
'col2': ['A', 'B', 'C', 'D', 'E'],
'col3': [1.1, 2.2, 3.3, 4.4, 5.5]
}
df = pd.DataFrame(data)
memory_usage = df.memory_usage(deep=True)
print(memory_usage)
Argumentas deep=True yra būtinas norint tiksliai apskaičiuoti objektų (eilučių) stulpelių atminties naudojimą.
Atminties naudojimo mažinimo metodai
1. Tinkamų duomenų tipų pasirinkimas
Tinkamo duomenų tipo pasirinkimas kiekvienam stulpeliui yra pats svarbiausias žingsnis mažinant atminties naudojimą. Pandas automatiškai nustato duomenų tipus, tačiau dažnai numato daugiau atminties reikalaujančius tipus nei reikia. Pavyzdžiui, stulpeliui, kuriame yra sveikieji skaičiai nuo 0 iki 100, gali būti priskirtas `int64` tipas, nors pakaktų `int8` arba `uint8`.
Pavyzdys: skaitinių tipų mažinimas
Galite sumažinti skaitinių tipų atvaizdus naudodami pd.to_numeric() funkciją su parametru downcast:
def reduce_mem_usage(df):
"""Iterate through all the columns of a dataframe and modify the data type
to reduce memory usage.
"""
start_mem = df.memory_usage().sum() / 1024**2
print('Memory usage of dataframe is {:.2f} MB'.format(start_mem))
for col in df.columns:
if df[col].dtype == 'object':
continue # Skip strings, handle them separately
col_type = df[col].dtype
if col_type in ['int64','int32','int16']:
c_min = df[col].min()
c_max = df[col].max()
if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
df[col] = df[col].astype(np.int8)
elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
df[col] = df[col].astype(np.int16)
elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
df[col] = df[col].astype(np.int32)
else:
df[col] = df[col].astype(np.int64)
elif col_type in ['float64','float32']:
c_min = df[col].min()
c_max = df[col].max()
if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
df[col] = df[col].astype(np.float16)
elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
df[col] = df[col].astype(np.float32)
else:
df[col] = df[col].astype(np.float64)
end_mem = df.memory_usage().sum() / 1024**2
print('Memory usage after optimization is: {:.2f} MB'.format(end_mem))
print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))
return df
Pavyzdys: eilučių konvertavimas į kategorinius tipus
Jei stulpelyje yra ribotas unikalių eilučių reikšmių skaičius, konvertavimas į kategorinį tipą gali žymiai sumažinti atminties naudojimą. Kategoriniai tipai saugo unikalias reikšmes tik vieną kartą ir atvaizduoja kiekvieną stulpelio elementą kaip sveikojo skaičiaus kodą, nurodantį unikalias reikšmes.
df['col2'] = df['col2'].astype('category')
Įsivaizduokite pasaulinės el. prekybos platformos klientų operacijų duomenų rinkinį. Stulpelyje „Šalis“ gali būti tik keli šimtai unikalių šalių pavadinimų, o duomenų rinkinyje yra milijonai operacijų. Stulpelio „Šalis“ konvertavimas į kategorinį tipą žymiai sumažintų atminties suvartojimą.
2. Skaidymas į dalis ir iteracija
Kai dirbate su labai dideliais duomenų rinkiniais, kurie netelpa į atmintį, galite apdoroti duomenis dalimis naudodami parametrą chunksize pd.read_csv() arba pd.read_excel(). Tai leidžia įkelti ir apdoroti duomenis mažesnėmis, valdomomis dalimis.
for chunk in pd.read_csv('large_dataset.csv', chunksize=100000):
# Process the chunk (e.g., perform calculations, filtering, aggregation)
print(f"Processing chunk with {len(chunk)} rows")
# Optionally, append results to a file or database.
Pavyzdys: didelių žurnalo failų apdorojimas
Įsivaizduokite, kad apdorojate didžiulį pasaulinės tinklo infrastruktūros žurnalo failą. Žurnalo failas yra per didelis, kad tilptų į atmintį. Naudodami skaidymą į dalis, galite kartoti žurnalo failą, analizuoti kiekvieną dalį dėl konkrečių įvykių ar šablonų ir apibendrinti rezultatus neviršydami atminties ribų.
3. Tik reikalingų stulpelių pasirinkimas
Dažnai duomenų rinkiniuose yra stulpelių, kurie nėra susiję su jūsų analize. Tik reikalingų stulpelių įkėlimas gali žymiai sumažinti atminties naudojimą. Norimus stulpelius galite nurodyti naudodami parametrą usecols pd.read_csv().
df = pd.read_csv('large_dataset.csv', usecols=['col1', 'col2', 'col3'])
Pavyzdys: pardavimo duomenų analizė
Jei analizuojate pardavimo duomenis, kad nustatytumėte geriausiai parduodamus produktus, jums gali prireikti tik stulpelių „Produkto ID“, „Pardavimo kiekis“ ir „Pardavimo pajamos“. Tik šių stulpelių įkėlimas sumažins atminties suvartojimą, palyginti su viso duomenų rinkinio įkėlimu, kuriame gali būti klientų demografiniai duomenys, pristatymo adresai ir kita nesusijusi informacija.
4. Retų duomenų struktūrų naudojimas
Jei jūsų DataFrame yra daug trūkstamų reikšmių (NaN) arba nulių, galite naudoti retas duomenų struktūras, kad efektyviau atvaizduotumėte duomenis. Reti DataFrames saugo tik nepraleistas arba nulinės reikšmes, žymiai sumažindami atminties naudojimą, kai dirbate su retais duomenimis.
sparse_series = df['col1'].astype('Sparse[float]')
sparse_df = sparse_series.to_frame()
Pavyzdys: klientų įvertinimų analizė
Įsivaizduokite klientų įvertinimų duomenų rinkinį dideliam produktų skaičiui. Dauguma klientų įvertins tik nedidelę produktų pogrupį, todėl susidarys reta įvertinimų matrica. Naudojant retą DataFrame šių duomenų saugojimui, žymiai sumažės atminties suvartojimas, palyginti su tankiu DataFrame.
5. Duomenų kopijavimo vengimas
Pandas operacijos kartais gali sukurti DataFrames kopijas, todėl padidėja atminties naudojimas. Duomenų keitimas DataFrame vietoje (kai įmanoma) gali padėti išvengti nereikalingo kopijavimo.
Pavyzdžiui, vietoj:
df = df[df['col1'] > 10]
Apsvarstykite galimybę naudoti:
df.drop(df[df['col1'] <= 10].index, inplace=True)
Argumentas inplace=True tiesiogiai modifikuoja DataFrame nesukuriant kopijos.
6. Eilučių saugyklos optimizavimas
Eilučių stulpeliai gali sunaudoti daug atminties, ypač jei juose yra ilgos eilutės arba daug unikalių reikšmių. Eilučių konvertavimas į kategorinius tipus, kaip minėta anksčiau, yra vienas veiksmingas metodas. Kitas būdas yra naudoti mažesnius eilučių atvaizdus, jei įmanoma.
Pavyzdys: eilučių ilgio mažinimas
Jei stulpelyje yra identifikatoriai, kurie saugomi kaip eilutės, bet galėtų būti atvaizduojami kaip sveikieji skaičiai, konvertavimas į sveikuosius skaičius gali sutaupyti atminties. Pavyzdžiui, produktų ID, kurie šiuo metu saugomi kaip eilutės, pvz., „PROD-1234“, gali būti susieti su sveikojo skaičiaus ID.
7. Dask naudojimas didesniems nei atmintis duomenų rinkiniams
Duomenų rinkiniams, kurie iš tikrųjų yra per dideli, kad tilptų į atmintį, net ir naudojant skaidymą į dalis, apsvarstykite galimybę naudoti Dask. Dask yra lygiagretaus skaičiavimo biblioteka, kuri gerai integruojama su Pandas ir NumPy. Tai leidžia jums dirbti su didesniais nei atmintis duomenų rinkiniais, suskaidant juos į mažesnes dalis ir apdorojant lygiagrečiai per kelis branduolius ar net kelis įrenginius.
import dask.dataframe as dd
ddf = dd.read_csv('large_dataset.csv')
# Perform operations on the Dask DataFrame (e.g., filtering, aggregation)
result = ddf[ddf['col1'] > 10].groupby('col2').mean().compute()
Metodas compute() suaktyvina faktinį skaičiavimą ir grąžina Pandas DataFrame, kuriame yra rezultatai.
Geriausia praktika ir aspektai
- Profilio kodas: naudokite profiliavimo įrankius, kad nustatytumėte atminties kliūtis ir sutelktumėte optimizavimo pastangas į labiausiai įtakos turinčias sritis.
- Išbandykite skirtingus metodus: optimalus atminties sumažinimo metodas priklauso nuo specifinių jūsų duomenų rinkinio savybių. Eksperimentuokite su skirtingais būdais, kad rastumėte geriausią sprendimą savo naudojimo atvejui.
- Stebėkite atminties naudojimą: stebėkite atminties naudojimą duomenų apdorojimo metu, kad įsitikintumėte, jog jūsų optimizavimai yra veiksmingi ir išvengtumėte atminties trūkumo klaidų.
- Supraskite savo duomenis: gilus duomenų supratimas yra labai svarbus norint pasirinkti tinkamiausius duomenų tipus ir optimizavimo metodus.
- Apsvarstykite kompromisus: kai kurie atminties optimizavimo metodai gali šiek tiek pabloginti našumą. Įvertinkite sumažinto atminties naudojimo naudą, palyginti su bet kokiu galimu poveikiu našumui.
- Dokumentuokite savo optimizavimus: aiškiai dokumentuokite atminties optimizavimo metodus, kuriuos įdiegėte, kad jūsų kodas būtų prižiūrimas ir suprantamas kitiems.
Išvada
Pandas atminties naudojimo optimizavimas yra būtinas norint efektyviai ir veiksmingai dirbti su dideliais duomenų rinkiniais. Suprasdami, kaip Pandas saugo duomenis, pasirinkdami tinkamus duomenų tipus, naudodami skaidymą į dalis ir naudodami kitus optimizavimo metodus, galite žymiai sumažinti atminties suvartojimą ir pagerinti duomenų analizės darbo eigos našumą. Šiame vadove pateikiama išsami pagrindinių metodų ir geriausios praktikos apžvalga, kaip įvaldyti atminties naudojimo sumažinimą Pandas. Nepamirškite profiliuoti savo kodo, išbandyti skirtingus metodus ir stebėti atminties naudojimą, kad pasiektumėte geriausių rezultatų savo konkrečiam naudojimo atvejui. Taikydami šiuos principus, galite išlaisvinti visą Pandas potencialą ir įveikti net reikliausius duomenų analizės iššūkius.
Įvaldydami šiuos metodus, duomenų mokslininkai ir analitikai visame pasaulyje gali tvarkyti didesnius duomenų rinkinius, pagerinti apdorojimo greitį ir gauti gilesnių įžvalgų iš savo duomenų. Tai prisideda prie efektyvesnių tyrimų, geriau pagrįstų verslo sprendimų ir galiausiai prie duomenimis pagrįsto pasaulio.