Pande za manipulaciju tabelama (Prvi deo)
Ako težite ka tome da vam pojam Big Data postane blizak i srodan, naravno da možete postići to ne znajuci mnogo toga o Pandama, ali time biste sebi uskratili velike beneficije koje dolaze sa ovom sjajnom pajtonovom bibliotekom. Možemo slobodno da kažemo kako je ovo najpoznatija biblioteka za manipulaciju tabelama koja čini osnovu svakog data engineera i data scientista. U prvom delu proći ćemo kroz neke osnovne stvari kako biste se upoznali sa mogućnostima pandi. Kao primer tabele u ovom blogu, koristio sam open source-ovanu tabelu sa statistikom NDPa zemalja sveta, a vi takodje možete da pronađete mnogo drugih tabela na UCI Repository koje možete koristiti za vežbu. Za prezentaciju sam koristio Jupyter Notebook, koji ima instant output, te je zbog toga veoma pogodan za ovakve stvari.
Počnimo sa osnovnim stvarima, kao što je očitavanje tabele, nakon što smo importovali biblioteku.
import pandas as pd
data = pd.read_csv('gdp_country.csv', skiprows=2, delimiter=',')
Varijabla koju ću koristiti od sada pa nadalje, jeste “data” i to mislim da je jasno svakome ko ima bar malo iskustva sa programiranjem. Sledeća stvar koju činim jeste očitavanje csv fajla, zatim u prvi parametar u zagradi je putanja do fajla koji ocitavam. U ovom slučaju fajl se nalazi u istom folderu kao i skripta. Parametar “skiprows” predstavlja ono što znači u bukvalnom prevodu, biramo koliko ćemo redova sa vrha tabele da preskočimo pri očitavanju iste. To je jedan od parametara koji se veoma retko koriste, ali sam u ovom slučaju namerno izabrao tabelu koja to zahteva jer ćete retko kad dobiti savrsene podatke. Delimiter predstavlja način razdvajanja vrednosti u fajlu, s obzirom da je ovo csv fajl (comma-separated values) jasno je da je delimiter zarez.
Nakon očitavanja dolazimo do prikaza tabele. Uglavnom je dovoljno da se pogledaju redovi pri vrhu kako bismo utvrdili da li je sve u redu sa tabelom, a tome nam služi funkcija .head().
data.head(2)
Sam izraz Big Data govori nam o tome da ćete često raditi sa velikim količinama podataka, sto znači da ćete imati neželjene kolone i redove, duplirane ili sa praznim vrednostima.
Ukoliko imate nepotrebne kolone ili redove, najbolji način da optimizujete memoriju pri radu jeste da ih jednostvano uklonimo.
Kada odbacujemo samo jednu kolonu to ćemo uraditi na sledeći način:
data.drop('column_to_drop', axis=1, inplace=True)
Za više kolona najbolji pristup je kreirati listu čiji će elementi biti nazivi kolona koje odbacujemo:
list_with_columns = ['column1_to_drop', 'column1_to_drop2', 'column1_to_drop3']
newdata = data.drop('list_with_columns', axis=1)
U slučaju da koristite .drop() funkciju, prvi parametar u zagradi je naziv kolone, ili liste u kojoj su nazivi kolona, drugim parametrom naznačavamo da se radi o kolonama.
Ako su nam potrebne samo kolone koje sadrže određeni string u nazivu:
data[data.columns.drop(list(data.filter(regex='string_we_need')))]
Funkcija “inplace” nam omogućava da novi output ostavimo trajno pod tom varijablom, ali ako dodeljujemo novu variablu, “inplace” je potrebno izuzeti.
Ako odbacujemo skoro sve kolone, lakši pristup je izabrati samo par neophodnih koje zadržavamo, a to radimo na sledeći način:
data = data[['Country Name', 'Country Code', 'Indicator name', '1965', '2009', '2011']]
Ako vam je potrebna nova tabela koja je potpuno ista kao prethodna to možete učiniti na sledeći način:
new_data = data
Ali ovo vam neće omogućiti da radite sa obe tabele nezavisno, kako biste to učinili, uradite sledeće:
new_data = data.copy()
Unoseci data.shape() dobijamo takozvani oblik dataframea, tj. broj kolona i redova.
Filtriranje ili selektovanje redova se i ne razlikuje mnogo od selektovanja kolona.
data = data[[data['Country Name']=='Angola']
Selektovanje više redova:
data = data[(data['Country Name']=='Angola') | (data['Country Name']=='Uruguay')]
Jos jedan od načina:
my_list_of_values = [‘Angola’, ‘Uruguay’]
data.loc[data['Country Name].isin(my_list_of_values)]
Da biste pogledali redove pri vrhu tabele, koristićete funkciju .head(), ali selektovanje nasumičnih redova u sredini tabele radimo na sledeći način:
data = data[134:142]
Ukoliko ipak želite random redove, to ćete dobiti funkcijom .sample(), a u zagradi navodite broj random redova koji želite:
data.sample(4)
Sada prelazimo na nešto što je često potrebno pri sređivanju dataseta, a to je promena naziva kolona.
data.rename(columns={'Country Name' : 'Name of country', 'Country Code' : 'Country Code'}, inplace=True)
Dodavanje sufiksa i prefiksa je veoma često neophodna, a pri tome je jednostavna rutina.
data = data.add_suffix('_added-suffix')
Razmak u nazivu kolona izmedju reči zna da izazove probleme, zbog toga je preporuka da se zameni sa donjom crtom:
data.columns = [x.strip().replace(' ','_') for x in data.columns]
Kada splitujemo sve vrednosti jedne kolone po nekom određenom karakteru, koristimo sledeću liniju koda, ali potrebno je obratiti pažnju da ne postoji nijedna NaN vrednost:
data['Indicator Name'].str.split(',').str[1]
Prosleđujemo naziv tabele (“data”), zatim naziv kolone (“Indicator Name”),nakon toga karakter po kom delimo vrednost, dok na kraju unosimo redni broj stringa koji povlačimo (started with zero).
Splitovanje u pandama je potpuno isto kao i u samom pythonu:
String = ‘2_under_score’
Splitted = String.split(‘_’)[1]
Out: ‘under’
Da bismo postavili željenu vrednost u jednu ili više ćelija, koristićemo jednostavnu funkciju .set_value() koja kao prva dva parametra prima broj reda i naziv kolone, a treći je vrednost koju želimo u ćeliji:
data.set_value(7, 'Indicator Name', 'Changed value in cell').inplace=True
Sada ćemo se pozabaviti NaN vrednostima sa osnovama grupisanja i sortiranja.
U ovu svrhu sam napravio novu kolonu nazvanu “Continent” po kojoj će da bude grupisana tabela koju ću sortirati po vrednostima 2011. godine, u opadajućem nizu.
data.sort_values(['2011'],ascending=False).groupby('Continent').head(5)
I ovo je manje-više sve što je potrebno da znate pre nego sto počnemo sa sređivanjem NaN vrednosti i duplikata.
U ovom slučaju je ocigledno da postoje NaN vrednosti, ali nekada će se jednostavno sakriti u sredinu tabele tako da će ih biti teško uočiti, u takvim slučajevima možemo koristiti funkciju isnull() unutar funkcije len() koja će nam prebrojati vrednosti:
len(data[data.Column.isnull()==True])
Način na koji ćemo se odnositi prema NaN vrednostima, zavisi od vaših potreba.
Odbacujući red koji ima u bar jednoj koloni NaN vrednost:
data.dropna(axis=0, inplace=True)
Odbacujući kolonu koja ima NaN vrednost u najmanje jednom redu:
data.dropna(axis=1, inplace=True)
Zamena NaN vrednosti sa stvarnom vrednosti, tj. dopunjavanje:
data.fillna(1)
Najčesći način dopunjavanja vrednosti jeste dopunjavanje sa brojem 1, posebno kada je u planu množenje, ali možete takođe dopuniti i sa bilo kojim stringom.
Odbacivanje duplikata je veoma jednostavno funkcijom:
data.drop_duplicates()
Imao sam slučaj sa velikim brojem dupliciranih redova sa potpuno istim ili veoma sličnim vrednostima, trebao sam uzeti maksimalnu vrednost(ovo zavisi od vaših potreba, često ćete uzimati prosek) u svim kolonama koje sadrže merenja, a grupisati po identifikacionim kolonama. To sam uradio na ovaj način i pokazalo se kao veoma ekifasno rešenje:
data.groupby(['Continent'])[['1965', '2009', '2011']].max()
Kao sto primećujete, ako kolonu ne navedete u groupby parametru, ili ne izvršite nikakvu agregaciju nad njom, ona se neće pojaviti u outputu. “Continent” je sada index ove tabele, kako bismo vratili kao kolonu, koristimo resetovanje indeksa:
data.reset_index(drop=False)
Parametar drop=True and drop=False, omogućava nam izbor da li ćemo zadržati ili odbaciti kolonu koja je indeksirana prethodno.
I za kraj, čuvanje tabele u CSV format odrađujemo na sledeći način:
data.to_csv(‘name_of_csv_file.csv’, index=False)
To bi bilo sve za prvi deo, u kom smo pisali o osnovnim funkcijama i mogućnostima popularne Pajtonove biblioteke, kao što su očitavanje podataka, rad nad kolonama i redovima kao i hendlovanje NaN vrednosti. U narednim delovima pisaću više o grupisanju, spajanju, pivotiranju, plotovanju i mnogim drugim stvarima koje čine pande tako sjajnim. Takođe ću da uključim više realnih problema sa kojima sam se susreo u svom radu, kao i primere rešenja. Ako imate bilo kakva pitanja, ne oklevajte. 🙂
*Tekst je originalno objavljen na engleskom jeziku na sajtu thingsolver.com