{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 8. Модификације табеле и записивање табеле у датотеку\n", "\n", "У овој лекцији ћемо говорити о:\n", "1. додавању нове врсте или колоне табели; и\n", "2. записивању табеле у датотеку." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 8.1. Додавање нове врсте или колоне табели" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Понекад је важно да вредности које смо израчунали на основу података у табели (на пример, просеке оцена по ученицима) и сачувамо у табели. Ако табела нема за то предвиђену колону или врсту лако је можемо додати!\n", "\n", "Вратимо се поново на пример са оценама ученика кога смо видели на раније:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "razred = [[\"Ana\", 5, 3, 5, 2, 4, 5],\n", " [\"Bojan\", 5, 5, 5, 5, 5, 5],\n", " [\"Vlada\", 4, 5, 3, 4, 5, 4],\n", " [\"Gordana\", 5, 5, 5, 5, 5, 5],\n", " [\"Dejan\", 3, 4, 2, 3, 3, 4],\n", " [\"Đorđe\", 4, 5, 3, 4, 5, 4],\n", " [\"Elena\", 3, 3, 3, 4, 2, 3],\n", " [\"Žaklina\", 5, 5, 4, 5, 4, 5],\n", " [\"Zoran\", 4, 5, 4, 4, 3, 5],\n", " [\"Ivana\", 2, 2, 2, 2, 2, 5],\n", " [\"Jasna\", 3, 4, 5, 4, 5, 5]]\n", "ocene = pd.DataFrame(razred)\n", "ocene.columns=[\"Ime\", \"Informatika\", \"Engleski\", \"Matematika\", \"Fizika\", \"Hemija\", \"Likovno\"]\n", "ocene1 = ocene.set_index(\"Ime\")\n", "ocene1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Овде смо прво увезли библиотеку *pandas* са скраћеним именом \"pd\", од листе података смо направили табелу, дали колонама имена и индексирали смо табелу по имену ученика.\n", "\n", "Као што смо раније видели, лако можемо да израчунамо просек оцена сваког ученика и да те податке испишемо. Међутим, ако желимо да просеке запамтимо у табели, треба нам нова колона. Нова колона се табели додаје тако што се просто напише:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ocene1[\"ProsekUc\"] = 0.0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ако покушамо да непостојећој колони додамо неку вредност, систем ће сам на крај табеле додати нову колону и попунити је наведеним вредностима:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ocene1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Сада ћемо у једном *for*-циклусу да прођемо кроз индексну колону табеле и да за сваки ред табеле израчунамо просек бројева уписаних у колоне \"Informatika\"--\"Likovno\". (Не смемо да рачунамо просек целог реда, јер редови сада садрже и колону \"ProsekUc\" која не сме да се укључи у рачун просека!)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for ucenik in ocene1.index:\n", " ocene1.loc[ucenik, \"ProsekUc\"] = ocene1.loc[ucenik, \"Informatika\":\"Likovno\"].mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ево како изгледа нова табела:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ocene1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Да бисмо израчунали просечну оцену за сваки предмет, додаћемо нову врсту:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ocene1.loc[\"ProsekPr\"] = 0.0\n", "ocene1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Овде треба да застанемо за тренутак и да се подсетимо да се запис облика `ocene1[\"ProsekUc\"]` односи на колоне табеле тако да ће наредба\n", "\n", " ocene1[\"ProsekUc\"] = 0.0\n", "\n", "додати нову колону попуњену нулама, док се запис `ocene1.loc[\"ProsekPr\"]` односи на врсте табеле, па ће наредба\n", "\n", " ocene1.loc[\"ProsekPr\"] = 0.0\n", "\n", "додати нову врсту попуњену нулама (што се и десило у примеру).\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for predmet in ocene1.columns:\n", " ocene1.loc[\"ProsekPr\", predmet] = ocene1.loc[\"Ana\":\"Jasna\", predmet].mean()\n", "ocene1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ево још једног примера. У фолдеру *podaci* се налази датотека *StanovnistvoSrbije2017.csv* која садржи процену броја становника Републике Србије по годинама на дан 31.12.2017. Први ред табеле представља заглавље табеле које нам каже да табела има три колоне (Старост, Мушко, Женско). Прво ћемо учитати табелу и индексирати је колоном \"Старост\":" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "stanovnistvo = pd.read_csv(\"podaci/StanovnistvoSrbije2017.csv\")\n", "stanovnistvo1 = stanovnistvo.set_index(\"Старост\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Сада ћемо урадити малу демографску анализу: израчунаћемо однос броја мушкараца и жена по годинама старости и приказаћемо податке линијским дијаграмом.\n", "\n", "Прво ћемо табели додати нову колону \"М/Ж\" и у ту колону уписати израчунате односе:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "stanovnistvo1[\"М/Ж\"] = 0.0\n", "for i in stanovnistvo1.index:\n", " stanovnistvo1.loc[i, \"М/Ж\"] = stanovnistvo1.loc[i, \"Мушко\"] / stanovnistvo1.loc[i, \"Женско\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ево првих неколико редова табеле:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "stanovnistvo1.head(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Потом ћемо приказати дијаграм коме ћемо додати линију на висини 1.0 да бисмо лакше уочили у ком тренутку број мушкараца постаје мањи од броја жена:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "plt.figure(figsize=(20,5))\n", "plt.plot(stanovnistvo1.index, stanovnistvo1[\"М/Ж\"])\n", "plt.plot(stanovnistvo1.index, [1.0] * len(stanovnistvo1.index))\n", "plt.title(\"Однос броја мушких и женских држављана Србије по годинама старости\\nпрема проценама броја становника на дан 31.12.2017\")\n", "plt.show()\n", "plt.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 8.2. Записивање табеле у датотеку\n", "\n", "Веома је важно омогућити да се подаци који су учитани из неке датотеке могу, након обраде, поново уписати у датотеку. Да ова могућност не постоји морали бисмо сваки пут изнова вршити обраду података, што у неким случајевима може да буде веома дуготрајан посао.\n", "\n", "Табела се уписује у датотеку типа *CSV* позивом функције `to_csv` (енгл. \"у csv\"). На пример, табелу `stanovnistvo1` смо модификовали тако што смо јој додали нову колону у коју смо уписали однос броја мушкараца и жена по узрастима. Ако желимо да тако модификовану табелу сачувамо под новим именом, то можемо учинити овако:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "stanovnistvo1.to_csv(\"podaci/StanovnistvoSrbije2017-Novo.csv\", encoding=\"utf-8\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Први податак који се прослеђује функцији `to_csv` представља име нове датотеке у коју ће бити уписани подаци, док аргумент `encoding=\"utf-8\"` значи да ће подаци бити уписани у датотеку користећи систем за кодирање који се зове *UTF-8*. Ово морамо да наведемо зато што у табели имамо податке који су записани ћирилицом. Чак и да смо користили латиницу морали бисмо да користимо UTF-8 систем за кодирање због слова као што су č, ć, š, ž, đ, а која не постоје у енглеском алфабету. Аргумент `encoding=\"utf-8\"` можемо да изоставимо само ако знамо да су за записивање података у табели коришћени искључиво симболи из енглеског алфабета.\n", "\n", "Ево примера. Са линка\n", "\n", " https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv\n", "\n", "ћемо учитати списак држава на свету и записаћемо ту табелу (без икаквих трансформација) у локалну датотеку *drzavesveta.csv* у фолдеру *podaci*:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "drzave = pd.read_csv(\"https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv\")\n", "drzave.to_csv(\"podaci/drzavesveta.csv\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ако сада из неког програма за уређивање текста (рецимо, *Notepad*) погледамо датотеку коју смо добили записивањем, видећемо да она изгледа овако (наведено је само првих неколико редова):\n", "\n", " ,Country,Region\n", " 0,Algeria,AFRICA\n", " 1,Angola,AFRICA\n", " 2,Benin,AFRICA\n", " 3,Botswana,AFRICA\n", " 4,Burkina,AFRICA\n", " 5,Burundi,AFRICA\n", " 6,Cameroon,AFRICA\n", " 7,Cape Verde,AFRICA\n", " 8,Central African Republic,AFRICA\n", " 9,Chad,AFRICA\n", " (итд)\n", "\n", "Приликом уписивања података у табелу Пајтон је уписао и индексну колону. Код табеле `stanovnistvo1` нам је то одговарало јер је табела била индексирана колоном \"Старост\". Овде нам то, ипак, не одговара зато што индексна колона не даје никакву важну информацију о подацима у табели. Ако желимо да упижемо табелу у датотеку, али тако да се индексна колона не уписује, можемо то урадити овако:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "drzave.to_csv(\"podaci/drzavesveta.csv\", index=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Сада у датотеци пише:\n", "\n", " Country,Region\n", " Algeria,AFRICA\n", " Angola,AFRICA\n", " Benin,AFRICA\n", " Botswana,AFRICA\n", " Burkina,AFRICA\n", " Burundi,AFRICA\n", " Cameroon,AFRICA\n", " Cape Verde,AFRICA\n", " Central African Republic,AFRICA\n", " Chad,AFRICA\n", " (итд)\n", "\n", "што смо и желели." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 8.3. Задаци\n", "\n", "Задатке реши у Џупитеру." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Задатак 1.** Погледај пажљиво наредбе у следећој ћелији, па одговори на питања:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "\n", "US = pd.read_html(\"https://simple.wikipedia.org/wiki/List_of_U.S._states\", header=[0,1])[0]\n", "US.to_csv(\"podaci/SAD.csv\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. У ком формату ће бити записани подаци из табеле \"US\"?\n", "2. Да ли ће подаци бити записани локално, или на неки удаљени ресурс?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Задатак 2.** Биолози су до данас описали око два милиона врста живих бића. Сва она су подељена у пет царстава. Њихов приближан број по царствима је дат следећом табелом:\n", "\n", "| Царство | Број врста |\n", "|--|--|\n", "| Животиње | 1.400.000 |\n", "| Биљке | 290.000 |\n", "| Гљиве | 100.000 |\n", "| Протисти | 200.000 |\n", "| Монере | 10.000 |\n", "\n", "Додај нову врсту табели која се зове \"Укупно\" и у њу унеси укупан број врста. Немој рачунати ручно, већ примени функцију `sum` на одговарајућу колону табеле." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Задатак 3.** У наредној ћелији дати су подаци о тежини (у килограмима) и дужини/висини (у центиметрима) једног дечака од његовог шестог месеца па до његових 6,5 година." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "merenja = [\"6 мес\", \"1,5 год\", \"2,5 год\", \"3,5 год\", \"4,5 год\", \"5,5 год\", \"6,5 год\"]\n", "masaKG = [5.9, 11.5, 14.8, 20.5, 22.0, 24.2, 29.0 ]\n", "visinaCM = [62.0, 84.0, 97.0, 115.0, 122.5, 131.5, 135.0 ]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Транспонуј табелу, тако транспонованој табели додај нову колону, па за свако мерење (што је сада врста у новој, транспонованој табели) израчунај *BMI* (*body mass index*) по формули:\n", "\n", "$$\\hbox{BMI} = \\frac{\\hbox{masa u kilogramima}}{(\\hbox{visina u metrima})^2}$$\n", "\n", "Добијену табелу упиши у датотеку *BMI.csv* (обрати пажњу на то да у табели имаш податке записане ћирилицом)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Задатак 4.** У следећој табели су приказане највише и најниже температуре (у Целзијусима) икада измерене на континентима:\n", "\n", "|Континент: | Европа | Азија | Африка | Северна Америка | Јужна Америка | Аустралија | Антарктик |\n", "|------------------------|--------|-------|--------|-----------------|---------------|------------|-----------|\n", "|Највиша забележена темп:| 48 | 54 | 55 | 56.7 | 48.9 | 50.7 | 19.8 |\n", "|Најнижа забележена темп:| -58.1 | -67.8 | -23.9 | -63 | -32.8 | -23 | -89.2 |\n", "\n", "(Подаци су преузети са странице https://www.space.com/17816-earth-temperature.html). Додај нови ред овој табели па у њега упиши максимални температурни распон за сваки континент, који се добија када се од највише забележене температуре одузме најнижа забележена температура." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Задатак 5.** У фолдеру *podaci* се налази датотека *StanovnistvoSrbije2017.csv* (која има заглавље). Табела има три колоне које се зову \"Старост\", \"Мушко\" и \"Женско\".\n", "\n", "*(а)* Учитај датотеку у структуру података *DataFrame* и индексирај табелу колоном \"Старост\"." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*(б)* Додај табели нову колону \"УкупноСт\" и онда израчунај и у ту колону упиши податак о томе колики је укупан процењени број становника по старости. Прикажи укупан процењени број становника по старости линијским дијаграмом." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*(в)* Додај табели нову врсту \"УкупноПол\" и онда израчунај и у ту врсту упиши податак о томе колики је укупан процењени број становника по полу. Прикажи укупан процењени број становника по полу секторским дијаграмом." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*(г)* На овај начин измењену табелу сними у датотеку *podaci.csv* (обрати пажњу на то да у табели имаш податке записане ћирилицом)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Задатак 6.** Ево трошкова живота једне породице током једне године, по месецима (сви износи су представљени у динарима):\n", " \n", " | Ставка | Јан | Феб | Мар | Апр | Мај | Јун | Јул | Авг | Сеп | Окт | Нов | Дец |\n", " |--------|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|\n", " | Станарина | 8.251 | 8.436 | 8.524 | 8.388 | 8.241 | 8.196 | 8.004 | 7.996 | 7.991 | 8.015 | 8.353 | 8.456 |\n", " | Струја | 4.321 | 4.530 | 4.115 | 3.990 | 3.985 | 3.726 | 3.351 | 3.289 | 3.295 | 3.485 | 3.826 | 3.834 |\n", " | Телефон (фиксни) | 1.425 | 1.538 | 1.623 | 1.489 | 1.521 | 1.485 | 1.491 | 1.399 | 1.467 | 1.531 | 1.410 | 1.385 |\n", " | Телефон (мобилни) | 2.181 | 2.235 | 2.073 | 1.951 | 1.989 | 1.945 | 3.017 | 2.638 | 2.171 | 1.831 | 1.926 | 1.833 |\n", " | ТВ и интернет | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 |\n", " | Превоз | 1.830 | 1.830 | 1.830 | 1.830 | 1.950 | 1.950 | 1.450 | 1.450 | 1.950 | 1.950 | 2.050 | 2.050 |\n", " | Храна | 23.250 | 23.780 | 24.019 | 24.117 | 24.389 | 24.571 | 24.736 | 24.951 | 25.111 | 25.389 | 25.531 | 25.923 |\n", " | Остало | 4.500 | 3.700 | 5.100 | 3.500 | 2.750 | 4.250 | 7.320 | 8.250 | 3.270 | 4.290 | 3.200 | 8.390 |\n", "\n", "У ћелији испод су исти подаци представљени листом:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "troskovi = [\n", " [\"Станарина\", 8251, 8436, 8524, 8388, 8241, 8196, 8004, 7996, 7991, 8015, 8353, 8456],\n", " [\"Струја\", 4321, 4530, 4115, 3990, 3985, 3726, 3351, 3289, 3295, 3485, 3826, 3834],\n", " [\"Телефон (фиксни)\", 1425, 1538, 1623, 1489, 1521, 1485, 1491, 1399, 1467, 1531, 1410, 1385],\n", " [\"Телефон (мобилни)\", 2181, 2235, 2073, 1951, 1989, 1945, 3017, 2638, 2171, 1831, 1926, 1833],\n", " [\"ТВ и интернет\", 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399 ],\n", " [\"Превоз\", 1830, 1830, 1830, 1830, 1950, 1950, 1450, 1450, 1950, 1950, 2050, 2050],\n", " [\"Храна\", 23250, 23780, 24019, 24117, 24389, 24571, 24736, 24951, 25111, 25389, 25531, 25923],\n", " [\"Остало\", 4500, 3700, 5100, 3500, 2750, 4250, 7320, 8250, 3270, 4290, 3200, 8390]\n", "]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*(а)* Представи табелу структуром *DataFrame*. Индексирај табелу." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*(б)* Додај табели нову врсту \"Укупно\" па у њу унеси укупне трошкове ове породице по месецима (колико је породица укупно потрошила у јануару, колико у фебруару итд)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*(в)* Додај табели нову колону \"Просечно\" па у њу унеси просечну потрошњу ове породице по ставкама (колико је породица просечно потрошила на станарину, колико на струју, итд)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*(г)* Добијену табелу упиши у датотеку *Troskovi.csv* водећи рачуна о томе да у табели има података који су записани ћирилицом." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.1" } }, "nbformat": 4, "nbformat_minor": 2 }