#!/usr/bin/env python # coding: utf-8 # # 11. час: Учитавање табела из локалних датотека и из удаљених ресурса # # На овом часу ћемо говорити о: # 1. учитавању података из табела које су припремљене у формату _CSV_; # 2. учитавање података из удаљених ресурса; и # 3. транспоновање табеле. # ## 11.1. Учитавање података из локалних _CSV_ датотека # # Видели смо у претходним примерима да се најмукотрпнији посао обраде података састоји у томе да се подаци унесу у табелу. То је досадан посао који се често састоји у томе да се подаци просто прекуцају. Табеле са којима смо се сретали су зато биле веома мале. Модерна обрада података се, међутим, све више усмерава на анализу _огромних_ количина података (енгл. _big data_) и ту прекуцавање података не долази у обзир. # # Подаци се данас углавном прикупљају аутоматски, и програми за прикупљање података генеришу велике табеле података које после треба обрађивати. Постоје разни формати за табеларно представљање података, а најједноставнији од њих се зове _CSV_, (од енгл. _comma separated values_ што значи "вредности раздвојене зарезима"). # # _CSV_ датотека је текстуална датотека у којој редови одговарају редовима табеле, а подаци унутар истог реда су раздвојени зарезима. На пример, у фолдеру _podaci_ се налази датотека _StanovnistvoSrbije2017.csv_ која изгледа овако: # # Старост,Мушко,Женско # 0,33145,31444 # 1,33252,31105 # 2,33807,31475 # 3,34076,31952 # 4,33436,31643 # 5,34278,32505 # 6,33773,31523 # 7,33892,32185 # 8,34706,32396 # 9,34519,32177 # 10,34017,32064 # 11,34947,33251 # ... (итд) ... # 84,11450,18529 # 85 и више,44817,78323 # # Ова табела садржи процену броја становника Републике Србије по годинама на дан 31.12.2017. Први ред табеле представља заглавље табеле које нам каже да табела има три колоне (Старост, Мушко, Женско). Врста # # 7,33892,32185 # # значи да се процењује да је 31.12.2017. у Србији било 33.892 седмогодишњих дечака и 32.185 седмогодишњих девојчица. # # Библиотека `pandas` има функцију `read_csv` која учитава _CSV_ датотеку и од ње прави табелу типа _DataFrame_. Ево примера: # In[ ]: # изврши ову ћелију import pandas as pd stanovnistvo = pd.read_csv("podaci/StanovnistvoSrbije2017.csv") # Пошто је табела велика, приказаћемо само првих неколико редова. Функција `head(N)` приказује првих N редова табеле (енгл. _head_ значи "глава"): # In[ ]: # изврши ову ћелију stanovnistvo.head(5) # Функција `tail(N)` приказује последњих N редова табеле (енгл. _tail_ значи "реп"): # In[ ]: # изврши ову ћелију stanovnistvo.tail(5) # Табелу ћемо индексирати колоном "Старост": # In[ ]: # изврши ову ћелију stanovnistvo1 = stanovnistvo.set_index("Старост") stanovnistvo1.head(5) # In[ ]: # изврши ову ћелију stanovnistvo1.tail(5) # ## 11.2. Учитавање података из удаљених ресурса # # Могуће је преузети и податке са удаљених ресурса без потребе да се они прво пребаце на локалну машину. Да бисмо приступили податку који се налази на некој другој машини потребно је да обе машине имају приступ Интернету и да знамо тачну локацију податка на удаљеној машини. Тачна локација било ког ресурса на Интернету је описана његовим _URL_-ом (од енгл. _Universal Resource Locator_, што значи "Универзални локатор ресурса"). # # На адреси # # https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv # # се налази јавно доступан списак свих држава на свету. Ову табелу можемо лако учитати наредбом `read_csv`: # In[ ]: # изврши ову ћелију drzave = pd.read_csv("https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv") drzave.head(10) # Помоћу наредбе `read_html` може се прочитати и табела директно из _HTML_ кода неке веб странице. Рецимо, следећа наредба чита списак свих федералних јединица Сједињених Америчких Држава са одговарајуће странице Википедије: # In[ ]: # изврши ову ћелију US = pd.read_html("https://simple.wikipedia.org/wiki/List_of_U.S._states", header=0)[0] # Наредба `read_html` враћа релативно сложену структуру, али табела коју желимо да видимо је прва у тој структури. Зато иза наредбе следи конструкт `[0]` који враћа прву компоненту сложене структуре. Аргумент `header=0` значи да прву врсту треба узети за заглавље табеле. Ево како изгледа табела: # In[ ]: # изврши ову ћелију US # ## 11.3. Транспоновање табеле # # Замена врста и колона табеле се зове _транспоновање_. Приликом транспоновања имена колона полазне табеле постају индекси нове табеле, док индексна колона полазне табеле одређује имена колона нове табеле: # # ![Транспоновање](slike/DataFrame-T.jpg) # # Транспоновање се често користи када табела има мало веома дугачких редова, па је у неким ситуацијама лакше посматрати транспоновану табелу која онда има пуно релативно кратких редова. Функције `head` и `tail` нам тада омогућују да се брзо упознамо са почетком и крајем табеле и да стекнемо неку интуицију о томе како табела изгледа. # # Важно је рећи и то да се са табелама може радити и без транспоновања, јер све што можемо да урадимо на колонама табеле можемо да урадимо и на врстама. И поред тога, транспоновање се често користи јер је библиотека `pandas` оптимизована за рад по колонама табеле. # # Табела се транспонује тако што се на њу примени функција `Т` која као резултат враћа нову, транспоновану табелу. # # Ево примера са оценама: # In[ ]: # изврши ову ћелију razred = [["Ана", 5, 3, 5, 2, 4, 5], ["Бојан", 5, 5, 5, 5, 5, 5], ["Влада", 4, 5, 3, 4, 5, 4], ["Гордана", 5, 5, 5, 5, 5, 5], ["Дејан", 3, 4, 2, 3, 3, 4], ["Ђорђе", 4, 5, 3, 4, 5, 4], ["Елена", 3, 3, 3, 4, 2, 3], ["Жаклина", 5, 5, 4, 5, 4, 5], ["Зоран", 4, 5, 4, 4, 3, 5], ["Ивана", 2, 2, 2, 2, 2, 5], ["Јасна", 3, 4, 5, 4, 5, 5]] ocene = pd.DataFrame(razred) ocene.columns=["Име", "Српски", "Енглески", "Математика", "Физика", "Хемија", "Ликовно"] ocene1 = ocene.set_index("Име") ocene1 # Транспоновану табелу добијамо овако: # In[ ]: # изврши ову ћелију ocene2 = ocene1.T ocene2 # Хајде још да се уверимо да су врсте и колоне замениле места и у пољима `index` и `columns`. У полазној табели је: # In[ ]: # изврши ову ћелију ocene1.index # In[ ]: # изврши ову ћелију ocene1.columns # А у транспонованој табели је: # In[ ]: # изврши ову ћелију ocene2.index # In[ ]: # изврши ову ћелију ocene2.columns # Како смо раније већ видели, просек оцена по предметима добијамо лако: # In[ ]: # изврши ову ћелију for predmet in ocene1.columns: print(predmet, "->", ocene1[predmet].mean()) # Да бисмо добили просек оцена по ученицима, можемо да приступимо врстама табеле користећи функцију `loc` како смо то већ видели, али можемо и да употребимо транспоновану табелу (рачунање просека по колонама, јер су колоне транспоноване табеле заправо врсте полазне табеле): # In[ ]: # изврши ову ћелију for ucenik in ocene2.columns: print(ucenik, "->", ocene2[ucenik].mean()) # Ево још једног примера. У фолдеру _podaci_ се налази датотека _TemperaturneAnomalije.csv_ која садржи податке о томе за колико степени Целзијуса је средња измерена температура на Земљи већа од оптималне у последњих 40 година. Ова табела има два дугачка реда који изгледају овако: # # 1977,1978,1979,1980,1981,... # 0.22,0.14,0.15,0.3,0.37,... # # У првом реду се налазе године (1977-2017), а у другом измерена температурна аномалија. Видимо да табела нема заглавље. Зато ћемо је учитати на следећи начин: # In[ ]: # изврши ову ћелију temp_anomalije = pd.read_csv("podaci/TemperaturneAnomalije.csv", header = None) temp_anomalije # Дакле, ако табела са подацима нема заглавље, приликом учитавања се то мора нагласити функцији `read_csv` тако што се наведе `header = None`. # # Да бисмо добили податке у облику који се лакше обрађује, транспоноваћемо табелу и онда ћемо колонама транспоноване табеле дати одговарајућа имена. # In[ ]: # изврши ову ћелију temp_anomalije1 = temp_anomalije.T temp_anomalije1.columns = ["Година", "Аномалија"] # Ево првих неколико редова табеле: # In[ ]: # изврши ову ћелију temp_anomalije1.head(10) # Табелу ћемо индексирати колоном "Година": # In[ ]: # изврши ову ћелију temp_anomalije2 = temp_anomalije1.set_index("Година") temp_anomalije2.head(5) # Приказаћемо температурне аномалије дијаграмом: # In[ ]: # изврши ову ћелију import matplotlib.pyplot as plt plt.figure(figsize=(15,5)) plt.plot(temp_anomalije2.index, temp_anomalije2["Аномалија"], color="r") plt.title("Температурне аномалије у периоду 1977--2017") plt.show() plt.close() # ## 11.4. Задаци # **Задатак 1.** У фолдеру _podaci_ се налази датотека _StanovnistvoSrbije2017.csv_ (која има заглавље). Табела има три колоне које се зову "Старост", "Мушко" и "Женско". # # _(а)_ Учитај датотеку у структуру података _DataFrame_ и индексирај табелу колоном "Старост". # _(б)_ Прикажи процењени број мушкараца и жена по старости линијским дијаграмом. # **Задатак 2.** Ученици једног разреда су скакали у даљ. Сваки ученик је скакао три пута и резултати су дати у датотеци _SkokUDalj.csv_ која се налази у фолдеру _podaci_. Табела има заглавље и састоји се од четири колоне: "Презиме и име", "Скок1", "Скок2" и "Скок3". # # _(а)_ Учитај датотеку у структуру података _DataFrame_. # _(б)_ Прикажи ове податке линијским дијаграмом који ће имати три линије, једна линија за сваки скок. Дијаграм треба да има легенду. # **Задатак 3.** На адреси # # https://raw.githubusercontent.com/resbaz/r-novice-gapminder-files/master/data/gapminder-FiveYearData.csv # # се налази јавно доступна табела са списком држава света и неким параметрима економског развоја тих држава праћеним у интервалима од 5 година. # # Табела има следеће колоне: # # * country = држава # * year = година на коју се односе подаци # * pop = број становника (енгл. _population_) # * continent = континент # * lifeExp = очекивани животни век у годинама (енгл. _life expextancy_) # * gdpPercap = БДП по глави становника у америчким доларима (енгл. _GDP per capitem_) # # Учитај ову табелу у структуру података _DataFrame_ и прикажи првих 20 редова табеле, као и последњих 10 редова табеле.