Садржај
Припрема
1. Увод у Џупитер (*Jupyter*)
2. Низови података и линијски дијаграми
3. Хистограми и боје
4. Просек и медијана низа бројева
5. Фреквенцијска анализа и секторски дијаграми
6. Табеларно представљени подаци
7. Индексирање и транспоновање табеле
8. Модификације табеле и записивање табеле у датотеку
9. Сортирање, филтрирање и фреквенцијска анализа
10. Џупитер и Ексел

Индексирање и транспоновање табеле

У овој лекцији ћемо говорити о:

  1. индексирању табеле ради флексибилнијег приступа елементима табеле;

  2. приступу врстама и појединачним локацијама индексиране табеле;

  3. рачунању са целим редовима и колонама табеле; и

  4. транспоновању табеле.

Индексирање

Видели смо да је рад са колонама табеле веома једноставан.

Да бисмо могли да радимо са редовима табеле треба прво да нађемо једну колону чија вредност једнозначно одређује цео ред табеле. На пример, у табели са прошлог часа

Подаци о групи деце

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()
   ...: 
../_images/J07slika1.png

Ознаке на хоризонталној оси узимамо из индексне колоне 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

Ево и кратке видео илустрације:

Транспоновање табеле

Замена врста и колона табеле се зове транспоновање. Приликом транспоновања имена колона полазне табеле постају индекси нове табеле, док индексна колона полазне табеле одређује имена колона нове табеле:

../_images/DataFrame-T.jpg

Транспоновање се често користи када табела има мало веома дугачких редова, па је у неким ситуацијама лакше посматрати транспоновану табелу која онда има пуно релативно кратких редова. Функције 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

(Created using Swinx, RunestoneComponents and PetljaDoc)
© 2022 Petlja
A- A+