U nastavku će biti prikazano nekoliko osnovnih funkcija za pripremu baze podataka.
# učitavanje biblioteke i provera aktuelne verzije
import pandas as pd
print(pd.__version__)
from google.colab import drive
drive.mount('/content/drive')
2.2.2
# Pravimo vektor koji će predstavljati naš skup podataka
d = [0,1,2,3,4,5,6,7,8,9]
# Pretvaramo skup podataka u DataFrame strukturu koja je pogodna za obradu
df = pd.DataFrame(d)
df
| 0 | |
|---|---|
| 0 | 0 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
| 9 | 9 |
# Isti DataFrame mogli smo napraviti i na sledeći način:
df1 = pd.DataFrame({'0': [0,1,2,3,4,5,6,7,8,9]})
df1
| 0 | |
|---|---|
| 0 | 0 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
| 9 | 9 |
# Prilikom ispisa DataFrame-a primećujemo da su u prvom primeru
# automatski dodeljena imena kolona i vrsta
# Sledećom komandom menjamo naziv kolone
df.columns = ['Rev']
df
| Rev | |
|---|---|
| 0 | 0 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
| 9 | 9 |
# Narednom komandom dodajemo novu kolonu pod nazivom datim kao argument
# Ovo je zapravo pristup nepostojećoj koloni koja će u tom slučaju biti dodata
# Ovakav pristup videli smo i u MATLAB-u kada pristupimo nepostojećem članu niza
df['NewCol'] = 5
df
| Rev | NewCol | |
|---|---|---|
| 0 | 0 | 5 |
| 1 | 1 | 5 |
| 2 | 2 | 5 |
| 3 | 3 | 5 |
| 4 | 4 | 5 |
| 5 | 5 | 5 |
| 6 | 6 | 5 |
| 7 | 7 | 5 |
| 8 | 8 | 5 |
| 9 | 9 | 5 |
# DataFrame sa vi[e kolona može se napraviti i direktno iz rečnika
# i ne moraju nužno sve kolone imati isti tip podataka:
df1 = pd.DataFrame(
{
'Rev': [0,1,2,3,4,5,6,7,8,9],
'Col': 5,
'Tmp': 'temp',
}
)
df1
| Rev | Col | Tmp | |
|---|---|---|---|
| 0 | 0 | 5 | temp |
| 1 | 1 | 5 | temp |
| 2 | 2 | 5 | temp |
| 3 | 3 | 5 | temp |
| 4 | 4 | 5 | temp |
| 5 | 5 | 5 | temp |
| 6 | 6 | 5 | temp |
| 7 | 7 | 5 | temp |
| 8 | 8 | 5 | temp |
| 9 | 9 | 5 | temp |
df1.dtypes
| 0 | |
|---|---|
| Rev | int64 |
| Col | int64 |
| Tmp | object |
# Ako pristupimo postojećeoj koloni, možemo izvršiti modifikaciju
# vrednosti u njoj.
df['NewCol'] = df['NewCol'] + 1
df
| Rev | NewCol | |
|---|---|---|
| 0 | 0 | 6 |
| 1 | 1 | 6 |
| 2 | 2 | 6 |
| 3 | 3 | 6 |
| 4 | 4 | 6 |
| 5 | 5 | 6 |
| 6 | 6 | 6 |
| 7 | 7 | 6 |
| 8 | 8 | 6 |
| 9 | 9 | 6 |
# Dodajemo kolonu test i col
df['test'] = 3
df['col'] = df['Rev']
df
| Rev | NewCol | test | col | |
|---|---|---|---|---|
| a | 0 | 6 | 3 | 0 |
| b | 1 | 6 | 3 | 1 |
| c | 2 | 6 | 3 | 2 |
| d | 3 | 6 | 3 | 3 |
| e | 4 | 6 | 3 | 4 |
| f | 5 | 6 | 3 | 5 |
| g | 6 | 6 | 3 | 6 |
| h | 7 | 6 | 3 | 7 |
| i | 8 | 6 | 3 | 8 |
| j | 9 | 6 | 3 | 9 |
# Možemo promeniti i nazive vrsta (indekse DataFrame-a)
i = ['a','b','c','d','e','f','g','h','i','j']
df.index = i
df
| Rev | NewCol | |
|---|---|---|
| a | 0 | 6 |
| b | 1 | 6 |
| c | 2 | 6 |
| d | 3 | 6 |
| e | 4 | 6 |
| f | 5 | 6 |
| g | 6 | 6 |
| h | 7 | 6 |
| i | 8 | 6 |
| j | 9 | 6 |
#Sada ćemo da pristupamo određenim delovima baze koristeći loc.
df.loc['a']
| a | |
|---|---|
| Rev | 0 |
| NewCol | 6 |
# Možemo pristupiti i delu od nekoliko vrsta prema njihovom nazivu,
# df.loc[inclusive:inclusive]
df.loc['a':'d']
| Rev | NewCol | |
|---|---|---|
| a | 0 | 6 |
| b | 1 | 6 |
| c | 2 | 6 |
| d | 3 | 6 |
# ili preko rednih brojeva vrsta funkcijom df.iloc[inclusive:exclusive]
df.iloc[0:3]
| Rev | NewCol | |
|---|---|---|
| a | 0 | 6 |
| b | 1 | 6 |
| c | 2 | 6 |
# Možemo pristupiti i delu od nekoliko kolona prema njihovom nazivu
df[['Rev', 'test']]
| Rev | test | |
|---|---|---|
| a | 0 | 3 |
| b | 1 | 3 |
| c | 2 | 3 |
| d | 3 | 3 |
| e | 4 | 3 |
| f | 5 | 3 |
| g | 6 | 3 |
| h | 7 | 3 |
| i | 8 | 3 |
| j | 9 | 3 |
# kombinacija pristupa
df.loc['a':'d','Rev']
| Rev | |
|---|---|
| a | 0 |
| b | 1 |
| c | 2 |
| d | 3 |
# pri logičkom indeksiranju, koristi se funkcija loc
df.loc[df['Rev']>3,:]
| Rev | NewCol | test | col | |
|---|---|---|---|---|
| e | 4 | 6 | 3 | 4 |
| f | 5 | 6 | 3 | 5 |
| g | 6 | 6 | 3 | 6 |
| h | 7 | 6 | 3 | 7 |
| i | 8 | 6 | 3 | 8 |
| j | 9 | 6 | 3 | 9 |
df.index[5:]
Index(['f', 'g', 'h', 'i', 'j'], dtype='object')
df.loc[df.index[5:],'col']
| col | |
|---|---|
| f | 5 |
| g | 6 |
| h | 7 |
| i | 8 |
| j | 9 |
# Pristup prvih N vrsta (default = 5)
df.head()
# print(df.dtypes)
| Rev | NewCol | test | col | |
|---|---|---|---|---|
| a | 0 | 6 | 3 | 0 |
| b | 1 | 6 | 3 | 1 |
| c | 2 | 6 | 3 | 2 |
| d | 3 | 6 | 3 | 3 |
| e | 4 | 6 | 3 | 4 |
# Pristup poslednjih N vrsta (default = 5)
df.tail(3)
# pronalaženje polja DataFrame-a koji ispunjavaju uslov
df[df > 3]
# df.loc['a':'d','Rev'].dtypes
# df.loc['a':'d','Rev'] > 3
# df>3
| Rev | NewCol | test | col | |
|---|---|---|---|---|
| a | NaN | 6 | NaN | NaN |
| b | NaN | 6 | NaN | NaN |
| c | NaN | 6 | NaN | NaN |
| d | NaN | 6 | NaN | NaN |
| e | 4.0 | 6 | NaN | 4.0 |
| f | 5.0 | 6 | NaN | 5.0 |
| g | 6.0 | 6 | NaN | 6.0 |
| h | 7.0 | 6 | NaN | 7.0 |
| i | 8.0 | 6 | NaN | 8.0 |
| j | 9.0 | 6 | NaN | 9.0 |
# funkcija isin: izdvajanje vrsta u kojima kolona 'Rev'
# ima vrednost iz zadatog skupa
df[df['Rev'].isin([3,5,7])]
| Rev | NewCol | test | col | |
|---|---|---|---|---|
| d | 3 | 6 | 3 | 3 |
| f | 5 | 6 | 3 | 5 |
| h | 7 | 6 | 3 | 7 |
# određivanje nekih statističkih veličina u DataFrame-u
df.mean()
| 0 | |
|---|---|
| Rev | 4.5 |
| NewCol | 6.0 |
| test | 3.0 |
| col | 4.5 |
df.mean(axis=1)
| 0 | |
|---|---|
| a | 2.25 |
| b | 2.75 |
| c | 3.25 |
| d | 3.75 |
| e | 4.25 |
| f | 4.75 |
| g | 5.25 |
| h | 5.75 |
| i | 6.25 |
| j | 6.75 |
print(df1.head(3))
print(df.head(3))
Rev Col Tmp 0 0 5 temp 1 1 5 temp 2 2 5 temp Rev NewCol test col a 0 6 3 0 b 1 6 3 1 c 2 6 3 2
# konkatenacija više DataFrame-ova
df2 = pd.concat([df,df1], ignore_index=True)
df2
| Rev | NewCol | test | col | Col | Tmp | |
|---|---|---|---|---|---|---|
| 0 | 0 | 6.0 | 3.0 | 0.0 | NaN | NaN |
| 1 | 1 | 6.0 | 3.0 | 1.0 | NaN | NaN |
| 2 | 2 | 6.0 | 3.0 | 2.0 | NaN | NaN |
| 3 | 3 | 6.0 | 3.0 | 3.0 | NaN | NaN |
| 4 | 4 | 6.0 | 3.0 | 4.0 | NaN | NaN |
| 5 | 5 | 6.0 | 3.0 | 5.0 | NaN | NaN |
| 6 | 6 | 6.0 | 3.0 | 6.0 | NaN | NaN |
| 7 | 7 | 6.0 | 3.0 | 7.0 | NaN | NaN |
| 8 | 8 | 6.0 | 3.0 | 8.0 | NaN | NaN |
| 9 | 9 | 6.0 | 3.0 | 9.0 | NaN | NaN |
| 10 | 0 | NaN | NaN | NaN | 5.0 | temp |
| 11 | 1 | NaN | NaN | NaN | 5.0 | temp |
| 12 | 2 | NaN | NaN | NaN | 5.0 | temp |
| 13 | 3 | NaN | NaN | NaN | 5.0 | temp |
| 14 | 4 | NaN | NaN | NaN | 5.0 | temp |
| 15 | 5 | NaN | NaN | NaN | 5.0 | temp |
| 16 | 6 | NaN | NaN | NaN | 5.0 | temp |
| 17 | 7 | NaN | NaN | NaN | 5.0 | temp |
| 18 | 8 | NaN | NaN | NaN | 5.0 | temp |
| 19 | 9 | NaN | NaN | NaN | 5.0 | temp |
# konkatenacija više DataFrame-ova
df3 = pd.concat([df,df1], axis=1)
df3
| Rev | NewCol | test | col | Rev | Col | Tmp | |
|---|---|---|---|---|---|---|---|
| a | 0.0 | 6.0 | 3.0 | 0.0 | NaN | NaN | NaN |
| b | 1.0 | 6.0 | 3.0 | 1.0 | NaN | NaN | NaN |
| c | 2.0 | 6.0 | 3.0 | 2.0 | NaN | NaN | NaN |
| d | 3.0 | 6.0 | 3.0 | 3.0 | NaN | NaN | NaN |
| e | 4.0 | 6.0 | 3.0 | 4.0 | NaN | NaN | NaN |
| f | 5.0 | 6.0 | 3.0 | 5.0 | NaN | NaN | NaN |
| g | 6.0 | 6.0 | 3.0 | 6.0 | NaN | NaN | NaN |
| h | 7.0 | 6.0 | 3.0 | 7.0 | NaN | NaN | NaN |
| i | 8.0 | 6.0 | 3.0 | 8.0 | NaN | NaN | NaN |
| j | 9.0 | 6.0 | 3.0 | 9.0 | NaN | NaN | NaN |
| 0 | NaN | NaN | NaN | NaN | 0.0 | 5.0 | temp |
| 1 | NaN | NaN | NaN | NaN | 1.0 | 5.0 | temp |
| 2 | NaN | NaN | NaN | NaN | 2.0 | 5.0 | temp |
| 3 | NaN | NaN | NaN | NaN | 3.0 | 5.0 | temp |
| 4 | NaN | NaN | NaN | NaN | 4.0 | 5.0 | temp |
| 5 | NaN | NaN | NaN | NaN | 5.0 | 5.0 | temp |
| 6 | NaN | NaN | NaN | NaN | 6.0 | 5.0 | temp |
| 7 | NaN | NaN | NaN | NaN | 7.0 | 5.0 | temp |
| 8 | NaN | NaN | NaN | NaN | 8.0 | 5.0 | temp |
| 9 | NaN | NaN | NaN | NaN | 9.0 | 5.0 | temp |
df1.columns = ['Rev','NewCol','test']
df2 = pd.concat([df,df1], ignore_index=True)
df2
| Rev | NewCol | test | col | |
|---|---|---|---|---|
| 0 | 0 | 6 | 3 | 0.0 |
| 1 | 1 | 6 | 3 | 1.0 |
| 2 | 2 | 6 | 3 | 2.0 |
| 3 | 3 | 6 | 3 | 3.0 |
| 4 | 4 | 6 | 3 | 4.0 |
| 5 | 5 | 6 | 3 | 5.0 |
| 6 | 6 | 6 | 3 | 6.0 |
| 7 | 7 | 6 | 3 | 7.0 |
| 8 | 8 | 6 | 3 | 8.0 |
| 9 | 9 | 6 | 3 | 9.0 |
| 10 | 0 | 5 | temp | NaN |
| 11 | 1 | 5 | temp | NaN |
| 12 | 2 | 5 | temp | NaN |
| 13 | 3 | 5 | temp | NaN |
| 14 | 4 | 5 | temp | NaN |
| 15 | 5 | 5 | temp | NaN |
| 16 | 6 | 5 | temp | NaN |
| 17 | 7 | 5 | temp | NaN |
| 18 | 8 | 5 | temp | NaN |
| 19 | 9 | 5 | temp | NaN |
df1.index=df.index
df3 = pd.concat([df,df1], axis=1)
df3
| Rev | NewCol | test | col | Rev | NewCol | test | |
|---|---|---|---|---|---|---|---|
| a | 0 | 6 | 3 | 0 | 0 | 5 | temp |
| b | 1 | 6 | 3 | 1 | 1 | 5 | temp |
| c | 2 | 6 | 3 | 2 | 2 | 5 | temp |
| d | 3 | 6 | 3 | 3 | 3 | 5 | temp |
| e | 4 | 6 | 3 | 4 | 4 | 5 | temp |
| f | 5 | 6 | 3 | 5 | 5 | 5 | temp |
| g | 6 | 6 | 3 | 6 | 6 | 5 | temp |
| h | 7 | 6 | 3 | 7 | 7 | 5 | temp |
| i | 8 | 6 | 3 | 8 | 8 | 5 | temp |
| j | 9 | 6 | 3 | 9 | 9 | 5 | temp |
Zadaci za samostalnu vežbu¶
Zadatak 1¶
Učitati bazu 3 vrste cvetova sa linka https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data u Pandas DataFrame. Nazivi kolona u bazi su redom: 'sepal_length', ' sepal_width', 'petal_length', 'petal_width', 'class'. Prikazati prvih 5 vrsta i poslednjih 5 vrsta. Proveriti koje su dimenzije baze. Šta predstavljaju vrste, a šta kolone?
petal_df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data',names=['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'class'])
## NOTE: this dataframe does not have a header row so you must put names=['col1_name',...] to specify it
# print(petal_df)
print(petal_df.columns)
print(petal_df.shape)
print(petal_df.head(5))
print(petal_df.tail(5))
Index(['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'class'], dtype='object')
(150, 5)
sepal_length sepal_width petal_length petal_width class
0 5.1 3.5 1.4 0.2 Iris-setosa
1 4.9 3.0 1.4 0.2 Iris-setosa
2 4.7 3.2 1.3 0.2 Iris-setosa
3 4.6 3.1 1.5 0.2 Iris-setosa
4 5.0 3.6 1.4 0.2 Iris-setosa
sepal_length sepal_width petal_length petal_width class
145 6.7 3.0 5.2 2.3 Iris-virginica
146 6.3 2.5 5.0 1.9 Iris-virginica
147 6.5 3.0 5.2 2.0 Iris-virginica
148 6.2 3.4 5.4 2.3 Iris-virginica
149 5.9 3.0 5.1 1.8 Iris-virginica
Zadatak 2¶
Izračunati nekoliko statističkih veličina svakog od obeležja (srednja vrednost, medijana, minimum, maksimum), ukupno i za svaku vrstu cveta posebno.
print(petal_df.describe())
print(petal_df.describe().loc['count':'mean','sepal_length':'petal_length'])
sepal_length sepal_width petal_length petal_width
count 150.000000 150.000000 150.000000 150.000000
mean 5.843333 3.054000 3.758667 1.198667
std 0.828066 0.433594 1.764420 0.763161
min 4.300000 2.000000 1.000000 0.100000
25% 5.100000 2.800000 1.600000 0.300000
50% 5.800000 3.000000 4.350000 1.300000
75% 6.400000 3.300000 5.100000 1.800000
max 7.900000 4.400000 6.900000 2.500000
sepal_length sepal_width petal_length
count 150.000000 150.000 150.000000
mean 5.843333 3.054 3.758667
Zadatak 3¶
Nacrtati raspodele obeležja 'sepal length' uporedo za svaku vrstu cveta, pomoću histograma, a potom pomoću boxplota. Da li se uočavaju neke razlike među vrstama cvetova? Nacrtati za svaku od vrsta cvetova, na zasebnim graficima, odnos obeležja 'sepal length' i 'sepal width', koristeći grafik rasipanja. Šta svaka tačka na grafiku predstavlja? Kakvi se zaključci mogu izvesti na osnovu dobijenih grafika?
import matplotlib.pyplot as plt
petal_classes = petal_df.loc[:,'class'].unique()
# print(petal_classes)
petals = [ petal_df[petal_df['class'] == petal_class].loc[:,['sepal_length','sepal_width']] for petal_class in petal_classes ]
for index,petal_data in enumerate(petals):
plt.hist(petal_data['sepal_length'],alpha=0.5,label=petal_classes[index])
plt.title('sepal_length')
plt.legend()
plt.show()
# print( [petal['sepal_length'] for petal in petals] )
plt.boxplot([petal['sepal_length'] for petal in petals] )
plt.show()
for index,petal in enumerate(petals):
plt.scatter(x=petal['sepal_length'],y=petal['sepal_width'],label= petal_classes[index])
plt.xlabel('sepal_length')
plt.ylabel('sepal_width')
plt.legend()
plt.show()
!jupyter nbconvert --to html "/content/drive/MyDrive/Colab Notebooks/06_pandas_prosireno_moja_rjesenja.ipynb"