Индексирање и транспоновање табеле¶
У овој лекцији ћемо говорити о:
индексирању табеле ради флексибилнијег приступа елементима табеле;
приступу врстама и појединачним локацијама индексиране табеле;
рачунању са целим редовима и колонама табеле; и
транспоновању табеле.
Индексирање¶
Видели смо да је рад са колонама табеле веома једноставан.
Да бисмо могли да радимо са редовима табеле треба прво да нађемо једну колону чија вредност једнозначно одређује цео ред табеле. На пример, у табели са прошлог часа
Ime |
Pol |
Starost |
Masa |
Visina |
---|---|---|---|---|
Ana |
ž |
13 |
46 |
160 |
Bojan |
m |
14 |
52 |
165 |
Vlada |
m |
13 |
47 |
157 |
Gordana |
ž |
15 |
54 |
165 |
Dejan |
m |
15 |
56 |
163 |
Đorđe |
m |
13 |
45 |
159 |
Elena |
ž |
14 |
49 |
161 |
Žaklina |
ž |
15 |
52 |
164 |
Zoran |
m |
15 |
57 |
167 |
Ivana |
ž |
13 |
45 |
158 |
Jasna |
ž |
14 |
51 |
162 |
колона „Ime” је таква колона (колона „Visina” није погодна јер имамо двоје деце са висином 165, па када кажемо „дете са висином 165” није јасно о коме се ради; исто тако ни колоне „Pol”, „Starost” и „Masa” нису погодне).
Таква колона се зове кључ јер је она кључна за приступање редовима табеле. Ако желимо да приступамо елементима табеле по редовима, морамо систему да пријавимо коју колону ћемо користити као кључ. То се постиже позивом функције set_index
којој проследимо име колоне, а она врати нову табелу „индексирану по датом кључу”:
In [1]: import pandas as pd
...: podaci = [["Ana", "ž", 13, 46, 160],
...: ["Bojan", "m", 14, 52, 165],
...: ["Vlada", "m", 13, 47, 157],
...: ["Gordana", "ž", 15, 54, 165],
...: ["Dejan", "m", 15, 56, 163],
...: ["Đorđe", "m", 13, 45, 159],
...: ["Elena", "ž", 14, 49, 161],
...: ["Žaklina", "ž", 15, 52, 164],
...: ["Zoran", "m", 15, 57, 167],
...: ["Ivana", "ž", 13, 45, 158],
...: ["Jasna", "ž", 14, 51, 162]]
...: tabela = pd.DataFrame(podaci)
...: tabela.columns=["Ime", "Pol", "Starost", "Masa", "Visina"]
...: tabela1=tabela.set_index("Ime")
...:
Нова табела (tabela1
) се од старе (tabela
) разликује само по томе што редови више нису индексирани бројевима (0, 1, 2, …) већ именима деце (Ana, Bojan, Vlada, …). Ево старе (неиндексиране табеле) која има колону „Ime” и чији редови су индексирани бројевима:
In [2]: tabela
Out[2]:
Ime Pol Starost Masa Visina
0 Ana ž 13 46 160
1 Bojan m 14 52 165
2 Vlada m 13 47 157
3 Gordana ž 15 54 165
4 Dejan m 15 56 163
5 Đorđe m 13 45 159
6 Elena ž 14 49 161
7 Žaklina ž 15 52 164
8 Zoran m 15 57 167
9 Ivana ž 13 45 158
10 Jasna ž 14 51 162
А ево и нове табеле у којој су редови индексирани именима деце:
In [3]: tabela1
Out[3]:
Pol Starost Masa Visina
Ime
Ana ž 13 46 160
Bojan m 14 52 165
Vlada m 13 47 157
Gordana ž 15 54 165
Dejan m 15 56 163
Đorđe m 13 45 159
Elena ž 14 49 161
Žaklina ž 15 52 164
Zoran m 15 57 167
Ivana ž 13 45 158
Jasna ž 14 51 162
Колона „Ime” је и даље присутна у табели tabela1
, али има посебан статус. Ако покушамо да јој приступимо као
„обичној” колони
tabela1["Ime"]
добићемо грешку. Међутим, она је ту као индексна колона:
In [4]: tabela1.index
Out[4]:
Index(['Ana', 'Bojan', 'Vlada', 'Gordana', 'Dejan', 'Đorđe', 'Elena',
'Žaklina', 'Zoran', 'Ivana', 'Jasna'],
dtype='object', name='Ime')
Ако желимо да прикажемо висину деце у групи графиконом тако да имена деце буду на хоризонталној оси, то сада можемо урадити овако:
In [5]: import matplotlib.pyplot as plt
...: plt.figure(figsize=(10,5))
...: plt.bar(tabela1.index, tabela1["Visina"])
...: plt.title("Visina dece u grupi")
...: plt.show()
...:

Ознаке на хоризонталној оси узимамо из индексне колоне tabela1.index
, док податке о висини стубића узимамо из колоне tabela1["Visina"]
.
Приступ врстама и појединачним ћелијама индексиране табеле¶
Структура података DataFrame је оптимизована за рад са колонама табеле. Срећом, када имамо индексирану табелу као што је то tabela1
, користећи функцију loc
(од енгл. location што значи „локација, положај, место”) можемо да приступамо редовима табеле, као и појединачним ћелијама табеле.
Податке о појединачним редовима табеле можемо да видимо овако:
In [6]: tabela1.loc["Dejan"]
Out[6]:
Pol m
Starost 15
Masa 56
Visina 163
Name: Dejan, dtype: object
Као аргумент функције loc
можемо да наведемо и распон, и тако ћемо добити одговарајући део табеле:
In [7]: tabela1.loc["Dejan":"Zoran"]
Out[7]:
Pol Starost Masa Visina
Ime
Dejan m 15 56 163
Đorđe m 13 45 159
Elena ž 14 49 161
Žaklina ž 15 52 164
Zoran m 15 57 167
Ако као други аргумент функције loc
наведемо име колоне, рецимо овако:
tabela1.loc["Dejan", "Visina"]
добићемо информацију о Дејановој висини.
In [8]: tabela1.loc["Dejan", "Visina"]
Out[8]: 163
Ево како можемо да добијемо информацију о маси и висини неколико деце:
In [9]: tabela1.loc["Dejan":"Zoran", "Masa":"Visina"]
Out[9]:
Masa Visina
Ime
Dejan 56 163
Đorđe 45 159
Elena 49 161
Žaklina 52 164
Zoran 57 167
Рачун по врстама и колонама табеле¶
Кренимо од једног примера. У ћелији испод дате су оцене неких ученика из информатике, енглеског, математике, физике, хемије и ликовног:
In [10]: razred = [["Ana", 5, 3, 5, 2, 4, 5],
....: ["Bojan", 5, 5, 5, 5, 5, 5],
....: ["Vlada", 4, 5, 3, 4, 5, 4],
....: ["Gordana", 5, 5, 5, 5, 5, 5],
....: ["Dejan", 3, 4, 2, 3, 3, 4],
....: ["Đorđe", 4, 5, 3, 4, 5, 4],
....: ["Elena", 3, 3, 3, 4, 2, 3],
....: ["Žaklina", 5, 5, 4, 5, 4, 5],
....: ["Zoran", 4, 5, 4, 4, 3, 5],
....: ["Ivana", 2, 2, 2, 2, 2, 5],
....: ["Jasna", 3, 4, 5, 4, 5, 5]]
....:
Сада ћемо од ових података направити табелу чије колоне ће се звати „Ime”, „Informatika”, „Engleski”, „Matematika”, „Fizika”, „Hemija”, „Likovno” и која ће бити индексирана по колони „Ime”:
In [11]: ocene = pd.DataFrame(razred)
....: ocene.columns=["Ime", "Informatika", "Engleski", "Matematika", "Fizika", "Hemija", "Likovno"]
....: ocene1 = ocene.set_index("Ime")
....: ocene1
....:
Out[11]:
Informatika Engleski Matematika Fizika Hemija Likovno
Ime
Ana 5 3 5 2 4 5
Bojan 5 5 5 5 5 5
Vlada 4 5 3 4 5 4
Gordana 5 5 5 5 5 5
Dejan 3 4 2 3 3 4
Đorđe 4 5 3 4 5 4
Elena 3 3 3 4 2 3
Žaklina 5 5 4 5 4 5
Zoran 4 5 4 4 3 5
Ivana 2 2 2 2 2 5
Jasna 3 4 5 4 5 5
Ако желимо да израчунамо просек по предметима, треба на сваку колону ове табеле да применимо функцију mean
. Листа са именима свих колона табеле ocene1
се добија као ocene1.columns
, па сада само треба да прођемо кроз ову листу и за сваку колону да израчунамо просек:
In [12]: for predmet in ocene1.columns:
....: print(predmet, "->", round(ocene1[predmet].mean(), 2))
....:
Informatika -> 3.91
Engleski -> 4.18
Matematika -> 3.73
Fizika -> 3.82
Hemija -> 3.91
Likovno -> 4.55
Да бисмо израчунали просечне оцене сваког ученика функцију mean
ћемо применити на врсте табеле које добијамо позивом функције loc
. Погледајмо, прво, како то можемо да урадимо за једног ученика:
In [13]: print("Đorđe ima sledeće ocene:")
....: print(ocene1.loc["Đorđe"])
....: print("Prosek njegovih ocena je:", round(ocene1.loc["Đorđe"].mean(), 2))
....:
Đorđe ima sledeće ocene:
Informatika 4
Engleski 5
Matematika 3
Fizika 4
Hemija 5
Likovno 4
Name: Đorđe, dtype: int64
Prosek njegovih ocena je: 4.17
Списак свих ученика се налази у индексној колони, па просеке по свим ученицима можемо да израчунамо овако:
In [14]: for ucenik in ocene1.index:
....: print(ucenik, "->", round(ocene1.loc[ucenik].mean(), 2))
....:
Ana -> 4.0
Bojan -> 5.0
Vlada -> 4.17
Gordana -> 5.0
Dejan -> 3.17
Đorđe -> 4.17
Elena -> 3.0
Žaklina -> 4.67
Zoran -> 4.17
Ivana -> 2.5
Jasna -> 4.33
Ево и кратке видео илустрације:
Транспоновање табеле¶
Замена врста и колона табеле се зове транспоновање. Приликом транспоновања имена колона полазне табеле постају индекси нове табеле, док индексна колона полазне табеле одређује имена колона нове табеле:

Транспоновање се често користи када табела има мало веома дугачких редова, па је у неким ситуацијама лакше посматрати транспоновану табелу која онда има пуно релативно кратких редова. Функције head
и tail
нам тада омогућују да се брзо упознамо са почетком и крајем табеле и да стекнемо неку интуицију о томе како табела изгледа.
Важно је рећи и то да се са табелама може радити и без транспоновања, јер све што можемо да урадимо на колонама табеле можемо да урадимо и на врстама. И поред тога, транспоновање се често користи јер је библиотека pandas
оптимизована за рад по колонама табеле.
Табела се транспонује тако што се на њу примени функција Т
која као резултат враћа нову, транспоновану табелу.
Ево примера са оценама:
In [15]: ocene1
Out[15]:
Informatika Engleski Matematika Fizika Hemija Likovno
Ime
Ana 5 3 5 2 4 5
Bojan 5 5 5 5 5 5
Vlada 4 5 3 4 5 4
Gordana 5 5 5 5 5 5
Dejan 3 4 2 3 3 4
Đorđe 4 5 3 4 5 4
Elena 3 3 3 4 2 3
Žaklina 5 5 4 5 4 5
Zoran 4 5 4 4 3 5
Ivana 2 2 2 2 2 5
Jasna 3 4 5 4 5 5
Транспоновану табелу добијамо овако:
In [16]: ocene2 = ocene1.T
In [17]: ocene2
Out[17]:
Ime Ana Bojan Vlada Gordana Dejan Đorđe Elena Žaklina Zoran Ivana Jasna
Informatika 5 5 4 5 3 4 3 5 4 2 3
Engleski 3 5 5 5 4 5 3 5 5 2 4
Matematika 5 5 3 5 2 3 3 4 4 2 5
Fizika 2 5 4 5 3 4 4 5 4 2 4
Hemija 4 5 5 5 3 5 2 4 3 2 5
Likovno 5 5 4 5 4 4 3 5 5 5 5
Хајде још да се уверимо да су врсте и колоне замениле места и у пољима index
и columns
. У полазној табели је:
In [18]: ocene1.index
Out[18]:
Index(['Ana', 'Bojan', 'Vlada', 'Gordana', 'Dejan', 'Đorđe', 'Elena',
'Žaklina', 'Zoran', 'Ivana', 'Jasna'],
dtype='object', name='Ime')
In [19]: ocene1.columns
Out[19]: Index(['Informatika', 'Engleski', 'Matematika', 'Fizika', 'Hemija', 'Likovno'], dtype='object')
А у транспонованој табели је:
In [20]: ocene2.index
Out[20]: Index(['Informatika', 'Engleski', 'Matematika', 'Fizika', 'Hemija', 'Likovno'], dtype='object')
In [21]: ocene2.columns
Out[21]:
Index(['Ana', 'Bojan', 'Vlada', 'Gordana', 'Dejan', 'Đorđe', 'Elena',
'Žaklina', 'Zoran', 'Ivana', 'Jasna'],
dtype='object', name='Ime')
Како смо раније већ видели, просек оцена по предметима добијамо лако:
In [22]: for predmet in ocene1.columns:
....: print(predmet, "->", round(ocene1[predmet].mean(), 2))
....:
Informatika -> 3.91
Engleski -> 4.18
Matematika -> 3.73
Fizika -> 3.82
Hemija -> 3.91
Likovno -> 4.55
Да бисмо добили просек оцена по ученицима, можемо да приступимо врстама табеле користећи функцију loc
како смо то већ видели, али можемо и да употребимо транспоновану табелу (рачунање просека по колонама, јер су колоне транспоноване табеле заправо врсте полазне табеле):
In [23]: for ucenik in ocene2.columns:
....: print(ucenik, "->", round(ocene2[ucenik].mean(), 2))
....:
Ana -> 4.0
Bojan -> 5.0
Vlada -> 4.17
Gordana -> 5.0
Dejan -> 3.17
Đorđe -> 4.17
Elena -> 3.0
Žaklina -> 4.67
Zoran -> 4.17
Ivana -> 2.5
Jasna -> 4.33
Задаци¶
За вежбу покрени Џупитер окружење и реши задатке из радне свеске J07.ipynb