Moramo li svaki put učitavati iz početka

Kao i obično, pre nego što završimo sa radom, restartovaćemo kernel i izvršiti sve ćelije od početka kako bismo proverili da li kod ispravno radi. Međutim, opet dugo čekamo da se podaci učitaju. To je zato što svaki put učitavamo celu Excel tabelu, iako u daljem radu koristimo samo određene redove. Trebalo bi ovu fazu obrade podataka da optimizujemo tako da se ne učitava uvek sve iz početka.

Pokušaćemo da dođemo do rešenja uz pomoć ChatGPT-a. Slikaćemo deo ekrana tako da obuhvati prvih pet ćelija sa kodom:

Slikanje ćelija sa kodom

U novom četu ChatGPT-a ćemo pejstovati slikan deo ekrana i dodati:

Ovo je početak jupyter sveske. Svaki put kada uradim „restart the kernel and run all cells” ponovo se učitava cela tabela Excel-a i onda uzima samo deo te tabele za dalji rad, što dugo traje. Mogu li nekako da izbegnem da se to ponavlja posle svakog restartovanja kernel-a?

ChatGPT vam može dati sledeći odgovor:

Odgovor *ChatGPT*-a u vezi ponovnog učitavanja

Naime, umesto da se iz Excel fajla svaki put učitava cela tabela, ideja je da se nakon restartovanja kernel-a iz posebnog fajla učita samo vrednost promenljive df2024. Da bismo to omogućili, treba da najpre sačuvamo vrednost promenljive df2024 u taj fajl.

U odgovoru se navodi da u tu svrhu možemo koristiti sledeću liniju koda:

df2024.to_parquet("df2024.parquet")

Nećemo ulaziti u detalje formata Parquet. Važno je da onako kako smo sačuvali tako posle bude i učitano.

U nastavku odgovora dat je sledeći kod:

 1import os
 2import pandas as pd
 3
 4if os.path.exists("df2024.parquet"):
 5    df2024 = pd.read_parquet("df2024.parquet")
 6else:
 7    df = pd.read_excel("Osnovno obrazovanje - Odeljenja i razredi.xlsx")
 8    df = df.rename(columns={'Vrsta ustanove ': 'Vrsta ustanove', 
 9                            ' Vrsta Osnivaca': 'Vrsta Osnivaca', 
10                            'Ukupan broj ucenika':'Broj ucenika'})
11    df2024 = df[(df["Skolska godina"]=="2024/2025") & (df["Vrsta ustanove"]=="Основна школа")]
12    df2024.to_parquet("df2024.parquet")

Naredba if proverava da li fajl postoji navođenjem uslova os.path.exists("df2024.parquet"). Ako fajl postoji, izvršiće se linija 5, a u suprotnom će se izvršiti linije 7−12. Dok je u ranijem primeru naredba if određivala da li se jedan blok koda izvršava ili ne, u ovom primeru ona određuje koji od dva bloka se izvršava. Prvi blok zovemo if-granom (linija 5), a drugi else-granom (linije 7−12).

Dakle, kada fajl df2024.parquet postoji, linija 5 učitava vrednost promenljive df2024 iz tog fajla.

Međutim, može se desiti da fajl df2024.parquet više ne postoji. Na primer, izbrisali smo ga. U tom slučaju, izvršava se else-grana. Linije 7−11 preuzete su iz ćelija koje smo i do sada izvršavali na početku. Ove linije učitavaju podatke iz Excel fajla i filtriraju redove. Linija 12 je nova i ona snima vrednost iz df2024 u fajl df2024.parquet.

Suštinski gledano, ako fajl obrišemo, efekat je isti kao da ga nismo ni pravili. To znači da nam isti kod pokriva i slučaj kada prvi put izvršavamo svesku. Promenićemo početak Jupyter sveske u skladu sa tim. Prve četiri ćelije sa kodom ćemo zameniti prethodnim parčetom koda. Ako i import naredbe izdvojimo u posebnu ćeliju, dobijamo sledeće:

Prve dve ćelije sa kodom

Prilikom izvršavanja koda može se desiti da nedostaje paket potreban za snimanje u Parquet format. U tom slučaju, treba instalirati paket koji se zove pyarrow, tj. dodati ga prvo u requirements.txt, a zatim ažurirati virtuelno okruženje projekta. Pošto je o instalaciji paketa već bilo reči u prethodnim lekcijama, ovog puta vas upućujemo na video lekciju ako želite da pratite kako taj postupak izgleda.

Nakon instalacije dodatnog paketa i ponovnog restartovanja kernel-a sa izvršavanjem svih ćelija, trebalo bi da sve bude uredno izvršeno. U File Browser-u JupyterLab-a primetićete novi fajl df2024.parquet:

Novi fajl df2024.parquet

U tom fajlu je sačuvan data frame iz promenljive df2024. Prilikom prvog izvršavanja fajl df2024.parquet nije postojao i kreiran je na kraju else-grane. Kada sledeći put restartujemo kernel i izvršimo sve iz početka, fajl df2024.parquet će postojati i biće izvršena if-grana koja će učitati df2024 iz tog fajla.

Da bismo mogli da vidimo koliko traje izvršavanje jedne, a koliko druge grane, treba da znamo kako da uključimo merenje vremena izvršavanja ćelije. Pogađate, i to ćemo pitati ChatGPT:

kako da vidim vreme izvršavanja ćelije u jupyteru

Odgovor o tome kako se meri vreme izvršavanja

Ono što nam treba navedeno je pod „2. Korišćenje %%time za celu ćeliju”. Naime, dovoljno je da na početak ćelije dodamo liniju %%time. Kada to uradimo i ponovo pokrenemo ćeliju, dobićemo:

Ponovno pokretanje ćelije sa time

Pri dnu prethodne slike vidimo da je izvršavanje trajalo 637 milisekundi, tj. oko 0.6 sekundi. Wall time meri stvarno vreme koje je proteklo, dok CPU time meri vreme tokom kojeg je procesor računara bio zauzet.

Pošto je u ovom slučaju fajl df2024.parquet već postojao, izvršena je if-grana koja bi trebalo da se izvršava brže. Pogledajmo šta se dešava kada obrišemo fajl df2024.parquet, pa ponovo izvršimo istu ćeliju:

Ponovno pokretanje ćelije sa time

Na ovoj slici vidimo da je izvršavanje trajalo 33.6 sekundi, što je preko 50 puta duže. Pošto fajl df2024.parquet nije postojao pre izvršavanja, izvršavana je else-grana u kojoj se prvo učitavaju svi podaci iz Excel-a, što dugo traje.

Ubuduće ćemo fajl df2024.parquet brisati samo kada iz nekog razloga želimo da se iz početka učitaju podaci iz Excel fajla i tada ćemo malo duže čekati.

Kada neka faza obrade podataka dugo traje, ne želite da je ponavljate ako ne morate. U takvim situacijama, bolje je da snimite međurezultat koji ćete učitati pri sledećem izvršavanju, nego da ponavljate celu obradu. U ovom segmentu lekcije smo vam dali primer kako to da uradite.