{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "87b669ad", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Päivitetty 2024-04-14 / Aki Taanila\n" ] } ], "source": [ "from datetime import datetime\n", "print(f'Päivitetty {datetime.now().date()} / Aki Taanila')" ] }, { "cell_type": "markdown", "id": "fa944ac2", "metadata": {}, "source": [ "# Tutustu Pythoniin ja pandas-kirjastoon\n", "\n", "Tästä muistiosta voit aloittaa vaikka et olisi koskaan koodannut Pythonilla.\n", "\n", "Paketti (kutsutaan myös kirjastoksi) on kokoelma valmista ohjelmakoodia, jota voin käyttää omissa ohjelmissani. Data-analytiikan peruspaketti on nimeltään **pandas**. Pandas sisältää muiden muassa valmiin **crosstab**-funktion, jolla voin laskea lukumäärä- ja prosenttiyhteenvetoja sekä **describe**-funktion, jolla voin nopeasti laskea tilastolliset tunnusluvut.\n", "\n", "Useimmat data-analytiikassa tarvittavat paketit sisältyvät Colabiin ja Anacondaan. Jos käytät Minicondaa, niin sinun pitää asentaa jokainen käytettävä paketti erikseen.\n", "\n", "Jos paketti on valmiiksi asennettu, niin voin tuoda sen käyttööni **import**-komennolla. Esimerkiksi `import pandas as pd` tuo pandas-paketin käyttööni siten että voin seuraavissa koodisoluissa viitata siihen lyhenteellä **pd**.\n", "\n", "Muistion solun voit suorittaa näppäinyhdistelmillä **ctrl-enter** (pysyt samassa solussa) tai **shift-enter** (siirryt seuraavaan soluun)." ] }, { "cell_type": "markdown", "id": "c5f1dc1a", "metadata": {}, "source": [ "## Datan lukeminen\n", "\n", "Pandas-paketin **read_excel**-funktiolla voin lukea datan Excel-tiedostosta. Jos tiedosto on samassa kansiossa kuin muistio, niin voin viitata siihen pelkällä tiedostonimellä, esimerkiksi **'data1.xlsx'**. Seuraavassa tiedosto on kuitenkin nettiosoitteessa. Luen seuraavassa data-objektin **df**-nimisen (voit käyttää haluamaasi nimeä) muuttujan arvoksi.\n", "\n", "Merkkijonot kirjoitetaan heittomerkkien tai lainausmerkkien väliin. Heittomerkin saat enter-näppäimen vierestä (samassa näppäimessä kuin tähti eli asteriski)." ] }, { "cell_type": "code", "execution_count": 2, "id": "9970901e", "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "\n", "df = pd.read_excel('https://taanila.fi/data1.xlsx')" ] }, { "cell_type": "markdown", "id": "5f34427d", "metadata": {}, "source": [ "Pandas-paketissa on määritelty **dataframe**-niminen tietorakenne, jota voit hyvin pitää Excel-taulukon vastineena. Edellä avattu data-olio **df** on dataframe.\n", "\n", "## Dataan tutustuminen\n", "\n", "Käsky `df` näyttää datan ensimmäisimmät ja viimeisimmät rivit." ] }, { "cell_type": "code", "execution_count": 3, "id": "51d375f5", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nrosukupikäperhekoulutuspalveluvpalkkajohtotyötovtyöymppalkkattyötehttyötervlomaosakuntosahieroja
0113811.022.0358733.0333NaNNaNNaNNaN
1212922.010.0296315.0213NaNNaNNaNNaN
2313011.07.0198934.01131.0NaNNaNNaN
3413621.014.0214433.03331.0NaNNaNNaN
4512412.04.0218323.02121.0NaNNaNNaN
...................................................
777812213.00.0159844.0434NaN1.01.0NaN
787913311.02.0163813.02121.0NaNNaNNaN
798012712.07.0261234.03331.0NaN1.0NaN
808113522.016.0280834.0333NaNNaNNaNNaN
818223523.015.0218334.04341.0NaNNaNNaN
\n", "

82 rows × 16 columns

\n", "
" ], "text/plain": [ " nro sukup ikä perhe koulutus palveluv palkka johto työtov työymp \\\n", "0 1 1 38 1 1.0 22.0 3587 3 3.0 3 \n", "1 2 1 29 2 2.0 10.0 2963 1 5.0 2 \n", "2 3 1 30 1 1.0 7.0 1989 3 4.0 1 \n", "3 4 1 36 2 1.0 14.0 2144 3 3.0 3 \n", "4 5 1 24 1 2.0 4.0 2183 2 3.0 2 \n", ".. ... ... ... ... ... ... ... ... ... ... \n", "77 78 1 22 1 3.0 0.0 1598 4 4.0 4 \n", "78 79 1 33 1 1.0 2.0 1638 1 3.0 2 \n", "79 80 1 27 1 2.0 7.0 2612 3 4.0 3 \n", "80 81 1 35 2 2.0 16.0 2808 3 4.0 3 \n", "81 82 2 35 2 3.0 15.0 2183 3 4.0 4 \n", "\n", " palkkat työteht työterv lomaosa kuntosa hieroja \n", "0 3 3 NaN NaN NaN NaN \n", "1 1 3 NaN NaN NaN NaN \n", "2 1 3 1.0 NaN NaN NaN \n", "3 3 3 1.0 NaN NaN NaN \n", "4 1 2 1.0 NaN NaN NaN \n", ".. ... ... ... ... ... ... \n", "77 3 4 NaN 1.0 1.0 NaN \n", "78 1 2 1.0 NaN NaN NaN \n", "79 3 3 1.0 NaN 1.0 NaN \n", "80 3 3 NaN NaN NaN NaN \n", "81 3 4 1.0 NaN NaN NaN \n", "\n", "[82 rows x 16 columns]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "markdown", "id": "5624560f", "metadata": {}, "source": [ "Dataframe-oliolla on lukuisia ominaisuuksia ja funktioita, joista jatkossa esimerkkejä. Huomaa, että \n", "\n", "* ominaisuuden nimen perässä ei ole sulkumerkkejä\n", "* funktion nimen perässä on aina sulkumerkit." ] }, { "cell_type": "markdown", "id": "dd9eacdb-1774-472b-a22e-7c3ce5b16fce", "metadata": {}, "source": [ "## Kategorinen vai määrällinen muuttuja\n", "\n", "* **nro** Tämä muuttuja on keinotekoinen järjestysnumero eikä muuttujan tyypillä ole merkitystä.\n", "* **sukup** Sukupuoli on kategorinen muuttuja. Tässä arvo 1 tarkoittaa miestä ja 2 naista.\n", "* **ika** Ikä on määrällinen muuttuja.\n", "* **perhe** Perhesuhde on kategorinen muuttuja. Tässä arvo 1 tarkoittaa perheetöntä ja 2 perheellistä.\n", "* **koulutus** Koulutus on kategorinen muuttuja (1 = peruskoulu, 2 = 2. aste, 3 = korkeakoulu, 4 = ylempi korkeakoulu).\n", "* **palveluv** Palvelusvuodet on määrällinen muuttuja.\n", "* **palkka** Palkka on määrällinen muuttuja.\n", "* **johto, työtov, työymp, palkkat, työteht** Nämä ovat tyytyväisyysmuuttujia, joiden arvo on välillä 1 = erittäin tyytymätön - 5 = erittäin tyytyväinen. Lähtökohtaisesti nämä ovat kategorisia muuttujia, mutta voidaan tulkita myös määrällisiksi muuttujiksi. Mielipideasteikot ovat usein rajatapauksia, joille voidaan käyttää sekä kategoristen että määrällisten muuttujien menetelmiä.\n", "* **työterv, lomaosa, kuntosa, hieroja** Nämä ovat kategorisia muuttujia, jotka kertovat onko vastaaja käyttänyt (**1**) kyseistä etua." ] }, { "cell_type": "code", "execution_count": 4, "id": "0ee67f11", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(82, 16)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# shape-ominaisuus sisältää rivien ja sarakkeiden lukumäärät\n", "df.shape" ] }, { "cell_type": "code", "execution_count": 5, "id": "0b31a86e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 82 entries, 0 to 81\n", "Data columns (total 16 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 nro 82 non-null int64 \n", " 1 sukup 82 non-null int64 \n", " 2 ikä 82 non-null int64 \n", " 3 perhe 82 non-null int64 \n", " 4 koulutus 81 non-null float64\n", " 5 palveluv 80 non-null float64\n", " 6 palkka 82 non-null int64 \n", " 7 johto 82 non-null int64 \n", " 8 työtov 81 non-null float64\n", " 9 työymp 82 non-null int64 \n", " 10 palkkat 82 non-null int64 \n", " 11 työteht 82 non-null int64 \n", " 12 työterv 47 non-null float64\n", " 13 lomaosa 20 non-null float64\n", " 14 kuntosa 9 non-null float64\n", " 15 hieroja 22 non-null float64\n", "dtypes: float64(7), int64(9)\n", "memory usage: 10.4 KB\n" ] } ], "source": [ "# info-funktio tulostaa tietoja datan sarakkeista\n", "df.info()" ] }, { "cell_type": "markdown", "id": "a4b11102", "metadata": {}, "source": [ "Yllä näkyvästä tulosteesta selviää, että tässä dataframessa on **int64** eli kokonaislukutyyppistä tietoa ja **float64** eli liukulukutyyppistä tietoa. Liukulukuja voit ajatella desimaalilukuina.\n", "\n", "Jos sarakkeessa olisi tekstimuotoista tietoa, niin se näyttäytyisi **object**-tyyppinä." ] }, { "cell_type": "code", "execution_count": 6, "id": "ba7b5c4a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([38, 29, 30, 36, 24, 31, 49, 55, 40, 33, 39, 35, 58, 53, 42, 26, 47,\n", " 44, 43, 56, 21, 45, 59, 37, 28, 50, 32, 51, 22, 34, 27, 41, 25, 61,\n", " 20, 52, 46], dtype=int64)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# unique-funktio tulostaa sarakkeen ainutkertaiset arvot (järjestys tulee datasta)\n", "df['ikä'].unique()" ] }, { "cell_type": "markdown", "id": "ed1aa53e", "metadata": {}, "source": [ "## Suodatuksia\n", "\n", "Datalle on helppo tehdä erilaisia suodatuksia. Dataframen sarakkeeseen voin viitata kirjoittamalla sarakkeen nimen hakasulkujen sisään, esimerkiksi `df['palkka']`. Suodatuksissa voin käyttää \n", "\n", "* vertailuoperaattoreita **>, <, >=, <=, ==, !=** \n", "* yhdistämisoperaattoreita **&** (ja), **|** (tai) \n", "* kielto-operaattoria **~**" ] }, { "cell_type": "code", "execution_count": 7, "id": "d645eab3", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nrosukupikäperhekoulutuspalveluvpalkkajohtotyötovtyöymppalkkattyötehttyötervlomaosakuntosahieroja
2313011.07.0198934.01131.0NaNNaNNaN
383913012.010.0230035.0334NaNNaNNaNNaN
434413012.07.0222323.04131.0NaNNaN1.0
\n", "
" ], "text/plain": [ " nro sukup ikä perhe koulutus palveluv palkka johto työtov työymp \\\n", "2 3 1 30 1 1.0 7.0 1989 3 4.0 1 \n", "38 39 1 30 1 2.0 10.0 2300 3 5.0 3 \n", "43 44 1 30 1 2.0 7.0 2223 2 3.0 4 \n", "\n", " palkkat työteht työterv lomaosa kuntosa hieroja \n", "2 1 3 1.0 NaN NaN NaN \n", "38 3 4 NaN NaN NaN NaN \n", "43 1 3 1.0 NaN NaN 1.0 " ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 30-vuotiaat\n", "df[df['ikä']==30]" ] }, { "cell_type": "code", "execution_count": 8, "id": "69f94572", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nrosukupikäperhekoulutuspalveluvpalkkajohtotyötovtyöymppalkkattyötehttyötervlomaosakuntosahieroja
252612612.03.0152124.02131.0NaN1.01.0
353613123.00.0155924.03131.0NaNNaNNaN
535412512.01.0155924.03121.0NaNNaNNaN
757613712.015.0159815.01111.0NaNNaNNaN
777812213.00.0159844.0434NaN1.01.0NaN
\n", "
" ], "text/plain": [ " nro sukup ikä perhe koulutus palveluv palkka johto työtov työymp \\\n", "25 26 1 26 1 2.0 3.0 1521 2 4.0 2 \n", "35 36 1 31 2 3.0 0.0 1559 2 4.0 3 \n", "53 54 1 25 1 2.0 1.0 1559 2 4.0 3 \n", "75 76 1 37 1 2.0 15.0 1598 1 5.0 1 \n", "77 78 1 22 1 3.0 0.0 1598 4 4.0 4 \n", "\n", " palkkat työteht työterv lomaosa kuntosa hieroja \n", "25 1 3 1.0 NaN 1.0 1.0 \n", "35 1 3 1.0 NaN NaN NaN \n", "53 1 2 1.0 NaN NaN NaN \n", "75 1 1 1.0 NaN NaN NaN \n", "77 3 4 NaN 1.0 1.0 NaN " ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Ne joiden koulutus ei ole 1 ja palkka on korkeintaan 1700 (huomaa sulkumerkit)\n", "df[(df['koulutus']!=1) & (df['palkka']<=1700)]" ] }, { "cell_type": "code", "execution_count": 9, "id": "e0f5045f", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nrosukupikäperhekoulutuspalveluvpalkkajohtotyötovtyöymppalkkattyötehttyötervlomaosakuntosahieroja
454625121.028.0198933.02231.0NaNNaN1.0
626325122.010.0187243.02231.0NaNNaNNaN
\n", "
" ], "text/plain": [ " nro sukup ikä perhe koulutus palveluv palkka johto työtov työymp \\\n", "45 46 2 51 2 1.0 28.0 1989 3 3.0 2 \n", "62 63 2 51 2 2.0 10.0 1872 4 3.0 2 \n", "\n", " palkkat työteht työterv lomaosa kuntosa hieroja \n", "45 2 3 1.0 NaN NaN 1.0 \n", "62 2 3 1.0 NaN NaN NaN " ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Yli 50-vuotiaat alle 2000 palkalla (huomaa sulkumerkit)\n", "df[(df['ikä']>50) & (df['palkka']<2000)]" ] }, { "cell_type": "code", "execution_count": 10, "id": "17683e90", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nrosukupikäperhekoulutuspalveluvpalkkajohtotyötovtyöymppalkkattyötehttyötervlomaosakuntosahieroja
464722213.021.0187233.0413NaNNaN1.0NaN
777812213.00.0159844.0434NaN1.01.0NaN
\n", "
" ], "text/plain": [ " nro sukup ikä perhe koulutus palveluv palkka johto työtov työymp \\\n", "46 47 2 22 1 3.0 21.0 1872 3 3.0 4 \n", "77 78 1 22 1 3.0 0.0 1598 4 4.0 4 \n", "\n", " palkkat työteht työterv lomaosa kuntosa hieroja \n", "46 1 3 NaN NaN 1.0 NaN \n", "77 3 4 NaN 1.0 1.0 NaN " ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Ne, jotka eivät ole käyttäneet työterveyshuoltoa ja joiden palkka alle 2000\n", "df[~(df['työterv']==1) & (df['palkka']<2000)]" ] }, { "cell_type": "markdown", "id": "d2cfc34d", "metadata": {}, "source": [ "## Funktion parametrit ja argumentit\n", "\n", "Funktioille voidaan antaa lisätietoa parametreinä. Esimerkiksi **nsmallest**-funktiolle mahdolliset parametrit löytyvät funktion ohjesivulta https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.nsmallest.html. Jos annat parametrien arvot funktion ohjesivun mukaisessa järjestyksessä, niin parametreja ei tarvitse nimetä. Parametrien nimeäminen on kuitenkin hyvä tapa. Esimerkiksi seuraavassa solussa voisin käyttää nimettyjä parametreja: `df.nsmallest(n=3, columns='palkka')`\n", "\n", "Terminologiaa: **n** ja **columns** ovat nsmallest-funktion parametrejä, joille voidaan antaa arvo. Parametrille annettavaa arvoa kutsutaan argumentiksi. Seuraavassa **3** on parametrin **n** arvo eli argumentti." ] }, { "cell_type": "code", "execution_count": 11, "id": "56d030d0", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nrosukupikäperhekoulutuspalveluvpalkkajohtotyötovtyöymppalkkattyötehttyötervlomaosakuntosahieroja
252612612.03.0152124.02131.0NaN1.01.0
353613123.00.0155924.03131.0NaNNaNNaN
535412512.01.0155924.03121.0NaNNaNNaN
\n", "
" ], "text/plain": [ " nro sukup ikä perhe koulutus palveluv palkka johto työtov työymp \\\n", "25 26 1 26 1 2.0 3.0 1521 2 4.0 2 \n", "35 36 1 31 2 3.0 0.0 1559 2 4.0 3 \n", "53 54 1 25 1 2.0 1.0 1559 2 4.0 3 \n", "\n", " palkkat työteht työterv lomaosa kuntosa hieroja \n", "25 1 3 1.0 NaN 1.0 1.0 \n", "35 1 3 1.0 NaN NaN NaN \n", "53 1 2 1.0 NaN NaN NaN " ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Rivit, joilla kolmen pienintä palkkaa\n", "df.nsmallest(3, 'palkka')" ] }, { "cell_type": "code", "execution_count": 12, "id": "752ee27c", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nrosukupikäperhekoulutuspalveluvpalkkajohtotyötovtyöymppalkkattyötehttyötervlomaosakuntosahieroja
565716122.036.031192NaN2151.0NaNNaN1.0
323315923.015.0627844.0544NaN1.0NaNNaN
131415823.021.0358745.0413NaNNaNNaNNaN
272825611.015.0222334.03241.0NaNNaN1.0
363725622.017.0272955.0555NaNNaNNaN1.0
\n", "
" ], "text/plain": [ " nro sukup ikä perhe koulutus palveluv palkka johto työtov työymp \\\n", "56 57 1 61 2 2.0 36.0 3119 2 NaN 2 \n", "32 33 1 59 2 3.0 15.0 6278 4 4.0 5 \n", "13 14 1 58 2 3.0 21.0 3587 4 5.0 4 \n", "27 28 2 56 1 1.0 15.0 2223 3 4.0 3 \n", "36 37 2 56 2 2.0 17.0 2729 5 5.0 5 \n", "\n", " palkkat työteht työterv lomaosa kuntosa hieroja \n", "56 1 5 1.0 NaN NaN 1.0 \n", "32 4 4 NaN 1.0 NaN NaN \n", "13 1 3 NaN NaN NaN NaN \n", "27 2 4 1.0 NaN NaN 1.0 \n", "36 5 5 NaN NaN NaN 1.0 " ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Rivit, joilla viisi korkeinta ikää\n", "df.nlargest(5, 'ikä')" ] }, { "cell_type": "markdown", "id": "9dcaf5cf", "metadata": {}, "source": [ "## Tilastolliset tunnusluvut\n", "\n", "**Describe**-funktio laskee tilastolliset tunnusluvut:\n", "\n", "* arvojen lukumäärä (count)\n", "* keskiarvo (mean)\n", "* keskihajonta (std)\n", "* pienin (min)\n", "* alaneljännes (25%); neljäsosa arvoista on korkeintaan alaneljänneksen suuruisia\n", "* mediaani (50%)\n", "* yläneljännes (75%); kolme neljäsosaa arvoista on korkeintaan yläneljänneksen suuruisia\n", "* suurin (max)." ] }, { "cell_type": "code", "execution_count": 13, "id": "5dec3bd7", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nrosukupikäperhekoulutuspalveluvpalkkajohtotyötovtyöymppalkkattyötehttyötervlomaosakuntosahieroja
count82.00000082.00000082.00000082.00000081.00000080.00000082.00000082.00000081.00000082.00000082.00000082.00000047.020.09.022.0
mean41.5000001.23170737.9512201.6219511.98765412.1750002563.8780493.0609764.0617283.2195122.1097563.1951221.01.01.01.0
std23.8152610.4245199.7738660.4878840.8440068.807038849.3503021.0581550.8268261.1549611.1111791.0475020.00.00.00.0
min1.0000001.00000020.0000001.0000001.0000000.0000001521.0000001.0000002.0000001.0000001.0000001.0000001.01.01.01.0
25%21.2500001.00000031.0000001.0000001.0000003.7500002027.0000002.0000004.0000003.0000001.0000003.0000001.01.01.01.0
50%41.5000001.00000037.5000002.0000002.00000012.5000002320.0000003.0000004.0000003.0000002.0000003.0000001.01.01.01.0
75%61.7500001.00000044.0000002.0000003.00000018.2500002808.0000004.0000005.0000004.0000003.0000004.0000001.01.01.01.0
max82.0000002.00000061.0000002.0000004.00000036.0000006278.0000005.0000005.0000005.0000005.0000005.0000001.01.01.01.0
\n", "
" ], "text/plain": [ " nro sukup ikä perhe koulutus palveluv \\\n", "count 82.000000 82.000000 82.000000 82.000000 81.000000 80.000000 \n", "mean 41.500000 1.231707 37.951220 1.621951 1.987654 12.175000 \n", "std 23.815261 0.424519 9.773866 0.487884 0.844006 8.807038 \n", "min 1.000000 1.000000 20.000000 1.000000 1.000000 0.000000 \n", "25% 21.250000 1.000000 31.000000 1.000000 1.000000 3.750000 \n", "50% 41.500000 1.000000 37.500000 2.000000 2.000000 12.500000 \n", "75% 61.750000 1.000000 44.000000 2.000000 3.000000 18.250000 \n", "max 82.000000 2.000000 61.000000 2.000000 4.000000 36.000000 \n", "\n", " palkka johto työtov työymp palkkat työteht \\\n", "count 82.000000 82.000000 81.000000 82.000000 82.000000 82.000000 \n", "mean 2563.878049 3.060976 4.061728 3.219512 2.109756 3.195122 \n", "std 849.350302 1.058155 0.826826 1.154961 1.111179 1.047502 \n", "min 1521.000000 1.000000 2.000000 1.000000 1.000000 1.000000 \n", "25% 2027.000000 2.000000 4.000000 3.000000 1.000000 3.000000 \n", "50% 2320.000000 3.000000 4.000000 3.000000 2.000000 3.000000 \n", "75% 2808.000000 4.000000 5.000000 4.000000 3.000000 4.000000 \n", "max 6278.000000 5.000000 5.000000 5.000000 5.000000 5.000000 \n", "\n", " työterv lomaosa kuntosa hieroja \n", "count 47.0 20.0 9.0 22.0 \n", "mean 1.0 1.0 1.0 1.0 \n", "std 0.0 0.0 0.0 0.0 \n", "min 1.0 1.0 1.0 1.0 \n", "25% 1.0 1.0 1.0 1.0 \n", "50% 1.0 1.0 1.0 1.0 \n", "75% 1.0 1.0 1.0 1.0 \n", "max 1.0 1.0 1.0 1.0 " ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.describe()" ] }, { "cell_type": "code", "execution_count": 14, "id": "17a8295f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "count 82.000000\n", "mean 2563.878049\n", "std 849.350302\n", "min 1521.000000\n", "25% 2027.000000\n", "50% 2320.000000\n", "75% 2808.000000\n", "max 6278.000000\n", "Name: palkka, dtype: float64" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# palkan tunnusluvut\n", "df['palkka'].describe()" ] }, { "cell_type": "markdown", "id": "b619baad", "metadata": {}, "source": [ "## Frekvenssitaulukko\n", "\n", "Seuraavassa sijoitan **crosstab**-funktion antaman tuloksen **df1**-nimisen muuttujan arvoksi. Tällöin tulosta ei näytetä ellen anna erikseen käskyä `df1`.\n", "\n", "Lisätietoa **crosstab**-funktion parametreista https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.crosstab.html" ] }, { "cell_type": "code", "execution_count": 15, "id": "5fe68a5d", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
col_0f
koulutus
1.027
2.030
3.022
4.02
\n", "
" ], "text/plain": [ "col_0 f\n", "koulutus \n", "1.0 27\n", "2.0 30\n", "3.0 22\n", "4.0 2" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1 = pd.crosstab(df['koulutus'], 'f')\n", "df1" ] }, { "cell_type": "markdown", "id": "7e11984e", "metadata": {}, "source": [ "Crosstab laskee frekvenssit eli esiintymiskertojen lukumäärät. Esimerkiksi koulutuksen 1 on suorittanut 27 henkilöä.\n", "\n", "Crosstab-funktion tuottama taulukko on dataframe kuten alkuperäinen datakin. Dataframe koostuu aina kolmesta osasta:\n", "\n", "* indeksi (**index**), joka näkyy vasemmassa reunassa\n", "* sarakeotsikot (**columns**), jotka näkyvät yläreunassa\n", "* varsinainen data; yhdessä sarakkeessa voi olla vain yhdentyyppistä dataa (esimerkiksi kokonaislukuja).\n", "\n", "Yllä indeksinä ovat koulutus-sarakkeessa esiintyneet arvot 1, 2, 3 ja 4. Sarakeotsikoina on ainoastaan f (minulla on tapana käyttää f:ää frekvenssin tunnuksena). Indeksillä on nimi (koulutus) ja sarakeotsikoilla on nimi (col_0)." ] }, { "cell_type": "code", "execution_count": 16, "id": "d2bfb111", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
f
koulutus
1.027
2.030
3.022
4.02
\n", "
" ], "text/plain": [ " f\n", "koulutus \n", "1.0 27\n", "2.0 30\n", "3.0 22\n", "4.0 2" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Vaihdan sarakeotsikoiden nimeksi tyhjän merkkijonon (peräkkäiset heittomerkit)\n", "df1.columns.name = ''\n", "df1" ] }, { "cell_type": "markdown", "id": "72984f91", "metadata": {}, "source": [ "**Lista** on Pythonin tietorakenne, joka kirjoitetaan hakasulkujen sisään. Seuraavassa määrittelen listan ja sijoitan sen dataframen indeksiin (**index**)." ] }, { "cell_type": "code", "execution_count": 17, "id": "40577477", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
f
Peruskoulu27
2. aste30
Korkeakoulu22
Ylempi korkeakoulu2
\n", "
" ], "text/plain": [ " f\n", "Peruskoulu 27\n", "2. aste 30\n", "Korkeakoulu 22\n", "Ylempi korkeakoulu 2" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "koulutus = ['Peruskoulu', '2. aste', 'Korkeakoulu', 'Ylempi korkeakoulu']\n", "df1.index = koulutus\n", "df1" ] }, { "cell_type": "markdown", "id": "b57e8f2d", "metadata": {}, "source": [ "Jos viittaan sarakkeeseen, jota ei ole vielä olemassa, niin sellainen luodaan. Seuraavassa luon sarakkeen, johon lasken prosentit." ] }, { "cell_type": "code", "execution_count": 18, "id": "c518273d", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
f%
Peruskoulu2733.333333
2. aste3037.037037
Korkeakoulu2227.160494
Ylempi korkeakoulu22.469136
\n", "
" ], "text/plain": [ " f %\n", "Peruskoulu 27 33.333333\n", "2. aste 30 37.037037\n", "Korkeakoulu 22 27.160494\n", "Ylempi korkeakoulu 2 2.469136" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Havaintojen lukumäärä\n", "n = df1['f'].sum()\n", "\n", "# Lisään %-sarakkeen\n", "df1['%'] = df1['f']/n*100\n", "\n", "df1" ] }, { "cell_type": "markdown", "id": "f1c53e70", "metadata": {}, "source": [ "Uuden rivin luomiseksi viittaan uuteen riviin **loc**-ominaisuudella. Seuraavassa lasken **sum**-funktiolla Yhteensä-rivin." ] }, { "cell_type": "code", "execution_count": 19, "id": "07dbf422", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
f%
Peruskoulu27.033.333333
2. aste30.037.037037
Korkeakoulu22.027.160494
Ylempi korkeakoulu2.02.469136
Yhteensä81.0100.000000
\n", "
" ], "text/plain": [ " f %\n", "Peruskoulu 27.0 33.333333\n", "2. aste 30.0 37.037037\n", "Korkeakoulu 22.0 27.160494\n", "Ylempi korkeakoulu 2.0 2.469136\n", "Yhteensä 81.0 100.000000" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1.loc['Yhteensä'] = df1.sum()\n", "df1" ] }, { "cell_type": "markdown", "id": "3d96a545", "metadata": {}, "source": [ "**VAROITUS!** Kokeile mitä tapahtuu Yhteensä-rivillä, jos suoritat yllä olevan solun uudelleen? Tämän jälkeen kannattaa suorittaa kaikki muistion solut uudelleen **Cell**-valikon komennolla **Run All**.\n", "\n", "Yllä mainitun varoituksen mukaisen vaaran voit välttää käyttämällä `df1.sum()` sijasta `df1.loc['Peruskoulu':'Ylempi korkeakoulu'].sum()`\n", "\n", "## Ristiintaulukointi\n", "\n", "Crosstab-funktiolla voin laskea myös ristiintaulukoinnin. Seuraavassa lasken koulutuksen ja sukupuolen välisen ristiintaulukoinnin." ] }, { "cell_type": "code", "execution_count": 20, "id": "3740f468", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sukup12
koulutus
1.0225
2.0237
3.0157
4.020
\n", "
" ], "text/plain": [ "sukup 1 2\n", "koulutus \n", "1.0 22 5\n", "2.0 23 7\n", "3.0 15 7\n", "4.0 2 0" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2 = pd.crosstab(df['koulutus'], df['sukup'])\n", "df2" ] }, { "cell_type": "markdown", "id": "48748766", "metadata": {}, "source": [ "Voin sijoittaa koulutuksen tekstimuotoiset arvot (aiemmin määrittelemäni lista) indeksiin. Luon myös sukupuoli-listan ja sijoitan sen arvot sarakeotsikoihin." ] }, { "cell_type": "code", "execution_count": 21, "id": "df02561c", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
MiesNainen
Peruskoulu225
2. aste237
Korkeakoulu157
Ylempi korkeakoulu20
\n", "
" ], "text/plain": [ " Mies Nainen\n", "Peruskoulu 22 5\n", "2. aste 23 7\n", "Korkeakoulu 15 7\n", "Ylempi korkeakoulu 2 0" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sukupuoli = ['Mies', 'Nainen']\n", "\n", "df2.index = koulutus\n", "df2.columns = sukupuoli\n", "df2" ] }, { "cell_type": "markdown", "id": "3abb729f", "metadata": {}, "source": [ "Dataframen indeksille voin antaa nimen. Samoin sarakeotsikoille voin antaa nimen." ] }, { "cell_type": "code", "execution_count": 22, "id": "e2317967", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
SukupuoliMiesNainen
Koulutus
Peruskoulu225
2. aste237
Korkeakoulu157
Ylempi korkeakoulu20
\n", "
" ], "text/plain": [ "Sukupuoli Mies Nainen\n", "Koulutus \n", "Peruskoulu 22 5\n", "2. aste 23 7\n", "Korkeakoulu 15 7\n", "Ylempi korkeakoulu 2 0" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2.index.name = 'Koulutus'\n", "df2.columns.name = 'Sukupuoli'\n", "df2" ] }, { "cell_type": "markdown", "id": "c64e74a8", "metadata": {}, "source": [ "## Dataframen käsittelyä" ] }, { "cell_type": "markdown", "id": "e673b360", "metadata": {}, "source": [ "Listan ohella **sanakirja** (**dictionary**) on toinen keskeinen pythonin tietorakenne. Sanakirja kirjoitetaan aaltosulkujen sisään ja se koostuu pareista. Parin jäsenet erotetaan toisistaan kaksoispisteellä.\n", "\n", "Seuraavassa käytän sanakirjaa **rename**-funktion yhteydessä kahden muuttujan (sarakkeen) uudelleen nimeämiseen." ] }, { "cell_type": "code", "execution_count": 23, "id": "eb27b5a0", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Index(['nro', 'sukupuoli', 'ikä', 'perhe', 'koulutus', 'palveluvuodet',\n", " 'palkka', 'johto', 'työtov', 'työymp', 'palkkat', 'työteht', 'työterv',\n", " 'lomaosa', 'kuntosa', 'hieroja'],\n", " dtype='object')" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = df.rename(columns={'sukup':'sukupuoli', 'palveluv':'palveluvuodet'})\n", "\n", "# Tarkistan onnistuiko uudelleen nimeäminen\n", "df.columns" ] }, { "cell_type": "markdown", "id": "2642b5fe", "metadata": {}, "source": [ "**VAROITUS!** Jos muuttujien uudelleen nimeämisen jälkeen palaat sellaiseen aiempaan soluun, jossa viitataan sukup- tai palveluv-muuttujaan, niin solun suorittaminen tuottaa virheilmoituksen. Tällaisessa tilanteessa kannattaa suorittaa kaikkien solujen koodit uudelleen **Cell**-valikon komennolla **Run All**" ] }, { "cell_type": "code", "execution_count": 24, "id": "f7474aac", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
SukupuoliMiesNainen
Koulutus
Peruskoulu225
Ylempi korkeakoulu20
Korkeakoulu157
2. aste237
\n", "
" ], "text/plain": [ "Sukupuoli Mies Nainen\n", "Koulutus \n", "Peruskoulu 22 5\n", "Ylempi korkeakoulu 2 0\n", "Korkeakoulu 15 7\n", "2. aste 23 7" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Indeksin järjestyksen vaihtaminen reindex-funktiolla\n", "df2.reindex(['Peruskoulu', 'Ylempi korkeakoulu', 'Korkeakoulu', '2. aste'])" ] }, { "cell_type": "markdown", "id": "be7a369d", "metadata": {}, "source": [ "Huomaa, että uusi järjestys ei tallennu dataframeen ellen varta vasten sijoita sitä df2:n arvoksi!" ] }, { "cell_type": "code", "execution_count": 25, "id": "96f657dd", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
SukupuoliNainenMies
Koulutus
Peruskoulu522
2. aste723
Korkeakoulu715
Ylempi korkeakoulu02
\n", "
" ], "text/plain": [ "Sukupuoli Nainen Mies\n", "Koulutus \n", "Peruskoulu 5 22\n", "2. aste 7 23\n", "Korkeakoulu 7 15\n", "Ylempi korkeakoulu 0 2" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Sarakkeiden järjestyksen vaihtamiseksi annan axis-parametrille arvon 1\n", "df2.reindex(['Nainen', 'Mies'], axis=1)" ] }, { "cell_type": "code", "execution_count": 26, "id": "4b36aa79", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
SukupuoliKoulutusMiesNainen
0Peruskoulu225
12. aste237
2Korkeakoulu157
3Ylempi korkeakoulu20
\n", "
" ], "text/plain": [ "Sukupuoli Koulutus Mies Nainen\n", "0 Peruskoulu 22 5\n", "1 2. aste 23 7\n", "2 Korkeakoulu 15 7\n", "3 Ylempi korkeakoulu 2 0" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Indeksin siirtäminen pois indeksistä; tilalle oletusindeksi 0, 1,...\n", "df2 = df2.reset_index()\n", "df2" ] }, { "cell_type": "code", "execution_count": 27, "id": "46edbe5c", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
SukupuoliMiesNainen
Koulutus
Peruskoulu225
2. aste237
Korkeakoulu157
Ylempi korkeakoulu20
\n", "
" ], "text/plain": [ "Sukupuoli Mies Nainen\n", "Koulutus \n", "Peruskoulu 22 5\n", "2. aste 23 7\n", "Korkeakoulu 15 7\n", "Ylempi korkeakoulu 2 0" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Koulutuksen palauttaminen indeksiin\n", "df2 = df2.set_index('Koulutus')\n", "df2" ] }, { "cell_type": "markdown", "id": "99a2f73a", "metadata": {}, "source": [ "**Loc**-ominaisuudella voin viitata datan \"viipaleisiin\" indeksin arvoja ja sarakeotsikoita käyttäen." ] }, { "cell_type": "code", "execution_count": 28, "id": "e92d8e5a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "23" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Kuinka monta 2. asteen koulutuksen suorittanutta miestä?\n", "df2.loc['2. aste', 'Mies']" ] }, { "cell_type": "markdown", "id": "e5dfdbcd", "metadata": {}, "source": [ "Pelkkä kaksoispiste tarkoittaa kaikkia rivejä tai kaikkia sarakkeita." ] }, { "cell_type": "code", "execution_count": 29, "id": "be04c21a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Koulutus\n", "Peruskoulu 5\n", "2. aste 7\n", "Korkeakoulu 7\n", "Ylempi korkeakoulu 0\n", "Name: Nainen, dtype: int64" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# df2:n 'Nainen'-sarakkeen kaikki rivit\n", "df2.loc[:, 'Nainen']" ] }, { "cell_type": "markdown", "id": "40e1b0e0", "metadata": {}, "source": [ "Edellä dataa on vain yhdessä sarakkeessa ja sen vuoksi tulos ei ole tyypiltään dataframe, vaan **series**. Voin kuitenkin vaihtaa tuloksen dataframeksi." ] }, { "cell_type": "code", "execution_count": 30, "id": "ba5dd14d", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Nainen
Koulutus
Peruskoulu5
2. aste7
Korkeakoulu7
Ylempi korkeakoulu0
\n", "
" ], "text/plain": [ " Nainen\n", "Koulutus \n", "Peruskoulu 5\n", "2. aste 7\n", "Korkeakoulu 7\n", "Ylempi korkeakoulu 0" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2.loc[:, 'Nainen'].to_frame()" ] }, { "cell_type": "code", "execution_count": 31, "id": "63ca5998", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
SukupuoliMiesNainen
Koulutus
Peruskoulu225
2. aste237
Korkeakoulu157
\n", "
" ], "text/plain": [ "Sukupuoli Mies Nainen\n", "Koulutus \n", "Peruskoulu 22 5\n", "2. aste 23 7\n", "Korkeakoulu 15 7" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Kaikki sarakkeet, mutta koulutuksesta jätetään Ylempi korkeakoulu pois\n", "df2.loc['Peruskoulu':'Korkeakoulu', :]" ] }, { "cell_type": "markdown", "id": "5dce9bf9", "metadata": {}, "source": [ "## Luokiteltu jakauma\n", "\n", "Luokkarajojen määrittämistä varten tarkistan pienimmän ja suurimman iän." ] }, { "cell_type": "code", "execution_count": 32, "id": "baa9f66e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "count 82.000000\n", "mean 37.951220\n", "std 9.773866\n", "min 20.000000\n", "25% 31.000000\n", "50% 37.500000\n", "75% 44.000000\n", "max 61.000000\n", "Name: ikä, dtype: float64" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df['ikä'].describe()" ] }, { "cell_type": "markdown", "id": "987c8350", "metadata": {}, "source": [ "Voin muodostaa luokkia pandas-kirjaston **cut**-funktiolla. Ensin määritän luokkarajat listana ja annan listan **bins**-parametrin arvoksi." ] }, { "cell_type": "code", "execution_count": 33, "id": "ba4d4220", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nrosukupuoliikäperhekoulutuspalveluvuodetpalkkajohtotyötovtyöymppalkkattyötehttyötervlomaosakuntosahierojaikäluokka
0113811.022.0358733.0333NaNNaNNaNNaN(29, 39]
1212922.010.0296315.0213NaNNaNNaNNaN(19, 29]
2313011.07.0198934.01131.0NaNNaNNaN(29, 39]
3413621.014.0214433.03331.0NaNNaNNaN(29, 39]
4512412.04.0218323.02121.0NaNNaNNaN(19, 29]
......................................................
777812213.00.0159844.0434NaN1.01.0NaN(19, 29]
787913311.02.0163813.02121.0NaNNaNNaN(29, 39]
798012712.07.0261234.03331.0NaN1.0NaN(19, 29]
808113522.016.0280834.0333NaNNaNNaNNaN(29, 39]
818223523.015.0218334.04341.0NaNNaNNaN(29, 39]
\n", "

82 rows × 17 columns

\n", "
" ], "text/plain": [ " nro sukupuoli ikä perhe koulutus palveluvuodet palkka johto \\\n", "0 1 1 38 1 1.0 22.0 3587 3 \n", "1 2 1 29 2 2.0 10.0 2963 1 \n", "2 3 1 30 1 1.0 7.0 1989 3 \n", "3 4 1 36 2 1.0 14.0 2144 3 \n", "4 5 1 24 1 2.0 4.0 2183 2 \n", ".. ... ... ... ... ... ... ... ... \n", "77 78 1 22 1 3.0 0.0 1598 4 \n", "78 79 1 33 1 1.0 2.0 1638 1 \n", "79 80 1 27 1 2.0 7.0 2612 3 \n", "80 81 1 35 2 2.0 16.0 2808 3 \n", "81 82 2 35 2 3.0 15.0 2183 3 \n", "\n", " työtov työymp palkkat työteht työterv lomaosa kuntosa hieroja \\\n", "0 3.0 3 3 3 NaN NaN NaN NaN \n", "1 5.0 2 1 3 NaN NaN NaN NaN \n", "2 4.0 1 1 3 1.0 NaN NaN NaN \n", "3 3.0 3 3 3 1.0 NaN NaN NaN \n", "4 3.0 2 1 2 1.0 NaN NaN NaN \n", ".. ... ... ... ... ... ... ... ... \n", "77 4.0 4 3 4 NaN 1.0 1.0 NaN \n", "78 3.0 2 1 2 1.0 NaN NaN NaN \n", "79 4.0 3 3 3 1.0 NaN 1.0 NaN \n", "80 4.0 3 3 3 NaN NaN NaN NaN \n", "81 4.0 4 3 4 1.0 NaN NaN NaN \n", "\n", " ikäluokka \n", "0 (29, 39] \n", "1 (19, 29] \n", "2 (29, 39] \n", "3 (29, 39] \n", "4 (19, 29] \n", ".. ... \n", "77 (19, 29] \n", "78 (29, 39] \n", "79 (19, 29] \n", "80 (29, 39] \n", "81 (29, 39] \n", "\n", "[82 rows x 17 columns]" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "bins = [19, 29, 39, 49, 59, 69]\n", "\n", "df['ikäluokka'] = pd.cut(df['ikä'], bins=bins)\n", "df\n", "# Ikäluokat löytyvät viimeisestä sarakkeesta" ] }, { "cell_type": "code", "execution_count": 34, "id": "b757d40c", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
f
ikäluokka
(19, 29]17
(29, 39]30
(39, 49]23
(49, 59]11
(59, 69]1
\n", "
" ], "text/plain": [ " f\n", "ikäluokka \n", "(19, 29] 17\n", "(29, 39] 30\n", "(39, 49] 23\n", "(49, 59] 11\n", "(59, 69] 1" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Luokiteltu jakauma:\n", "df3 = pd.crosstab(df['ikäluokka'], 'f')\n", "df3.columns.name = ''\n", "df3" ] }, { "cell_type": "markdown", "id": "50f96c95", "metadata": {}, "source": [ "## Ryhmittely\n", "\n", "Seuraavassa lasken palkalle tilastollisia tunnuslukuja koulutuksen määräämissä ryhmissä. Datan jakaminen ryhmiin sujuu **groupby**-funktiolla.\n", "\n", "Seuraavaa komentoon on hyvä perehtyä tarkemminkin. Koodissa operoidaan enimmäkseen **olio**illa (voidaan kutsua myös objekteiksi). \n", "\n", "Esimerkiksi **df** on **DataFrame**-luokan **olio**. DataFrame-luokan oliot tunnistavat **groupby**-funktion. Groupby-funktiolle pitää antaa parametrina sen muuttujan nimi, jonka mukaan ryhmitellään. Huomaa, että olion nimen ja funktion nimen välissä on aina **piste** (**.**). Samoin käytetään pistettä olion nimen ja ominaisuuden välissä (esimerkiksi **df.shape**).\n", "\n", "Groupby-funktion käytön seurauksena syntyy uusi olio, jonka 'palkka'-muuttujaan koodi viittaa. Tälle oliolle toteutetaan **describe**-funktio, joka laskee tilastolliset tunnusluvut.\n", "\n", "Komennot siis usein muodostuvat oliosta, funktioista (funktion kohdistaminen olioon muodostaa uuden olion) ja ominaisuuksista, jotka aina erotetaan toisistaan pisteellä." ] }, { "cell_type": "code", "execution_count": 35, "id": "40634165", "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
countmeanstdmin25%50%75%max
Peruskoulu27.02310.481481473.1086531638.02008.002144.02534.03587.0
2. aste30.02403.100000533.9843951521.02008.252378.52729.03510.0
Korkeakoulu22.02887.2272731108.4043841559.02222.252710.02925.06278.0
Ylempi korkeakoulu2.05147.000000110.3086585069.05108.005147.05186.05225.0
\n", "
" ], "text/plain": [ " count mean std min 25% 50% \\\n", "Peruskoulu 27.0 2310.481481 473.108653 1638.0 2008.00 2144.0 \n", "2. aste 30.0 2403.100000 533.984395 1521.0 2008.25 2378.5 \n", "Korkeakoulu 22.0 2887.227273 1108.404384 1559.0 2222.25 2710.0 \n", "Ylempi korkeakoulu 2.0 5147.000000 110.308658 5069.0 5108.00 5147.0 \n", "\n", " 75% max \n", "Peruskoulu 2534.0 3587.0 \n", "2. aste 2729.0 3510.0 \n", "Korkeakoulu 2925.0 6278.0 \n", "Ylempi korkeakoulu 5186.0 5225.0 " ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df4 = df.groupby('koulutus')['palkka'].describe()\n", "\n", "# Aiemmin määritelty koulutus-lista sisältää koulutusten tekstimuotoiset arvot\n", "df4.index = koulutus\n", "df4" ] }, { "cell_type": "code", "execution_count": 36, "id": "0e534dda", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Peruskoulu2. asteKorkeakouluYlempi korkeakoulu
count27.00000030.00000022.0000002.000000
mean2310.4814812403.1000002887.2272735147.000000
std473.108653533.9843951108.404384110.308658
min1638.0000001521.0000001559.0000005069.000000
25%2008.0000002008.2500002222.2500005108.000000
50%2144.0000002378.5000002710.0000005147.000000
75%2534.0000002729.0000002925.0000005186.000000
max3587.0000003510.0000006278.0000005225.000000
\n", "
" ], "text/plain": [ " Peruskoulu 2. aste Korkeakoulu Ylempi korkeakoulu\n", "count 27.000000 30.000000 22.000000 2.000000\n", "mean 2310.481481 2403.100000 2887.227273 5147.000000\n", "std 473.108653 533.984395 1108.404384 110.308658\n", "min 1638.000000 1521.000000 1559.000000 5069.000000\n", "25% 2008.000000 2008.250000 2222.250000 5108.000000\n", "50% 2144.000000 2378.500000 2710.000000 5147.000000\n", "75% 2534.000000 2729.000000 2925.000000 5186.000000\n", "max 3587.000000 3510.000000 6278.000000 5225.000000" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Voin halutessani transponoida dataframen\n", "df4.T" ] }, { "cell_type": "markdown", "id": "8e84fc38", "metadata": {}, "source": [ "## Luettelo muistiossa käytetyistä funktioista ja ominaisuuksista\n", "\n", "\n", "* Merkkijono (**string**) kirjoitetaan heittomerkkien '' väliin (myös lainausmerkit \"\" käyvät). Merkkijonoja ovat esimerkiksi tiedostonimet, dataframen sarakeotsikot (muuttujien nimet), muuttujien tekstimuotoiset arvot. Huomaa kuitenkin, että Pythonin muuttujien nimiä ei kirjoitetan heittomerkkien väliin (esimerkiksi df, n jne.) \n", "\n", "* Paketin tuonti **import**-toiminnolla; esimerkkinä **pandas**-paketin tuonti\n", "\n", "* Pythonin tietorakenne **lista**, joka kirjoitetaan hakasulkujen sisään\n", "* Pythonin tietorakenne **sanakirja** (**dictionary**), joka kirjoitetaan aaltosulkujen sisään\n", "* Pandas-kirjaston tietorakenteet **dataframe** ja **series**\n", "\n", "* **pd.read_excel()** datan lukeminen Excel-tiedostosta\n", "* **df.shape** datan rivien ja sarakkeiden lukumäärät\n", "* **df.info()** arvojen lukumäärät ja tietotyypit\n", "* **df.describe()** tilastolliset tunnusluvut\n", "* **df.nsmallest()** n pienintä nimetyn sarakkeen suhteen\n", "* **df.nlargest()** n suurinta nimetyn sarakkeen suhteen\n", "* **df[].unique()** nimetyn sarakkeen ainutkertaisten arvojen luettelo\n", "* **pd.crosstab()** lukumäärä- ja prosenttiyhteenvedot \n", "* **df.columns** sarakeotsikot\n", "* **df.index** riviotsikot\n", "* **df.columns.name** sarakeotsikoiden nimi\n", "* **df.index.name** riviotsikoiden nimi\n", "* **df.rename()** sarakeotsikoiden uudelleen nimeämiseen\n", "* **df.reindex()** sarkeotsikoiden tai indeksin uudelleen järjestäminen\n", "* **df.reset_index()** indeksin siirtäminen tavalliseksi sarakkeeksi (tilalle oletusindeksi)\n", "* **df.set_index()** sarakkeen siirtäminen indeksiin\n", "* **df.loc[]** viittaaminen dataframen \"viipaleeseen\"\n", "* **df.to_frame()** series dataframeksi\n", "* **pd.cut()** arvojen luokittelu\n", "* **df.groupby()** ryhmittely\n", "* **df.T** dataframen transponointi (rivien ja sarakkeiden vaihtaminen päittäin)\n", "\n", "Virhetilanteissa auttaa usein koodisolujen suoritus uudelleen **Run**-valikon komennolla **Run All**. Jos avaat aiemmin aloittamasi muistion, niin ensimmäiseksi kannattaa suorittaa koodisolut **Run**-valikon komennolla **Run All**" ] }, { "cell_type": "markdown", "id": "a8a421a2", "metadata": {}, "source": [ "## Lisätietoa\n", "\n", "\n", "Data-analytiikka Pythonilla https://tilastoapu.wordpress.com/python/" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.12.2" } }, "nbformat": 4, "nbformat_minor": 5 }