{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Päivitetty 2025-05-15 / Aki Taanila\n"
]
}
],
"source": [
"from datetime import datetime\n",
"print(f'Päivitetty {datetime.now().date()} / Aki Taanila')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Ryhmittelyjä groupby-funktiolla"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" nro | \n",
" sukup | \n",
" ikä | \n",
" perhe | \n",
" koulutus | \n",
" palveluv | \n",
" palkka | \n",
" johto | \n",
" työtov | \n",
" työymp | \n",
" palkkat | \n",
" työteht | \n",
" työterv | \n",
" lomaosa | \n",
" kuntosa | \n",
" hieroja | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 1 | \n",
" 1 | \n",
" 38 | \n",
" 1 | \n",
" 1.0 | \n",
" 22.0 | \n",
" 3587 | \n",
" 3 | \n",
" 3.0 | \n",
" 3 | \n",
" 3 | \n",
" 3 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
"
\n",
" \n",
" | 1 | \n",
" 2 | \n",
" 1 | \n",
" 29 | \n",
" 2 | \n",
" 2.0 | \n",
" 10.0 | \n",
" 2963 | \n",
" 1 | \n",
" 5.0 | \n",
" 2 | \n",
" 1 | \n",
" 3 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
"
\n",
" \n",
" | 2 | \n",
" 3 | \n",
" 1 | \n",
" 30 | \n",
" 1 | \n",
" 1.0 | \n",
" 7.0 | \n",
" 1989 | \n",
" 3 | \n",
" 4.0 | \n",
" 1 | \n",
" 1 | \n",
" 3 | \n",
" 1.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
"
\n",
" \n",
" | 3 | \n",
" 4 | \n",
" 1 | \n",
" 36 | \n",
" 2 | \n",
" 1.0 | \n",
" 14.0 | \n",
" 2144 | \n",
" 3 | \n",
" 3.0 | \n",
" 3 | \n",
" 3 | \n",
" 3 | \n",
" 1.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
"
\n",
" \n",
" | 4 | \n",
" 5 | \n",
" 1 | \n",
" 24 | \n",
" 1 | \n",
" 2.0 | \n",
" 4.0 | \n",
" 2183 | \n",
" 2 | \n",
" 3.0 | \n",
" 2 | \n",
" 1 | \n",
" 2 | \n",
" 1.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
"
\n",
" \n",
"
\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",
" 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 "
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.read_excel('https://taanila.fi/data1.xlsx')\n",
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"# Muuttujien tekstimuotoisia arvoja\n",
"sukup = ['Mies', 'Nainen']\n",
"koulutus = ['Peruskoulu', '2. aste', 'Korkeakoulu', 'Ylempi korkeakoulu']"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" | | \n",
" count | \n",
" mean | \n",
" std | \n",
" min | \n",
" 25% | \n",
" 50% | \n",
" 75% | \n",
" max | \n",
"
\n",
" \n",
" \n",
" \n",
" | Peruskoulu | \n",
" 27 | \n",
" 2310 | \n",
" 473 | \n",
" 1638 | \n",
" 2008 | \n",
" 2144 | \n",
" 2534 | \n",
" 3587 | \n",
"
\n",
" \n",
" | 2. aste | \n",
" 30 | \n",
" 2403 | \n",
" 534 | \n",
" 1521 | \n",
" 2008 | \n",
" 2378 | \n",
" 2729 | \n",
" 3510 | \n",
"
\n",
" \n",
" | Korkeakoulu | \n",
" 22 | \n",
" 2887 | \n",
" 1108 | \n",
" 1559 | \n",
" 2222 | \n",
" 2710 | \n",
" 2925 | \n",
" 6278 | \n",
"
\n",
" \n",
" | Ylempi korkeakoulu | \n",
" 2 | \n",
" 5147 | \n",
" 110 | \n",
" 5069 | \n",
" 5108 | \n",
" 5147 | \n",
" 5186 | \n",
" 5225 | \n",
"
\n",
" \n",
"
\n"
],
"text/plain": [
""
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Palkan tunnuslukuja koulutuksen määräämissä ryhmissä\n",
"df1 = df.groupby('koulutus')['palkka'].describe()\n",
"\n",
"# Koulutuksen tekstimuotoiset arvot numeroiden 1, 2, 3, 4 sijasta\n",
"df1.index = koulutus\n",
"\n",
"# Esitän tulokset ilman desimaaleja\n",
"df1.style.format('{:.0f}')"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" | | \n",
" Peruskoulu | \n",
" 2. aste | \n",
" Korkeakoulu | \n",
" Ylempi korkeakoulu | \n",
"
\n",
" \n",
" \n",
" \n",
" | Mies | \n",
" 2354 | \n",
" 2461 | \n",
" 3145 | \n",
" 5147 | \n",
"
\n",
" \n",
" | Nainen | \n",
" 2121 | \n",
" 2211 | \n",
" 2334 | \n",
" - | \n",
"
\n",
" \n",
"
\n"
],
"text/plain": [
""
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Palkkakeskiarvoja sukupuolen ja koulutuksen määräämissä ryhmissä\n",
"# unstack() siirtää koulutukset sarakkeisiin\n",
"df2 = df.groupby(['sukup', 'koulutus'])['palkka'].mean().unstack()\n",
"\n",
"# Sukupuolen ja koulutuksen tekstimuotoiset arvot\n",
"df2.index = sukup\n",
"df2.columns = koulutus\n",
"\n",
"# Esitän tulokset ilman desimaaleja\n",
"# puuttuvan arvon tilalle '-'\n",
"df2.style.format('{:.0f}', na_rep='-')"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" | | \n",
" Peruskoulu | \n",
" 2. aste | \n",
" Korkeakoulu | \n",
" Ylempi korkeakoulu | \n",
"
\n",
" \n",
" \n",
" \n",
" | Mies | \n",
" 2354 | \n",
" 2461 | \n",
" 3145 | \n",
" 5147 | \n",
"
\n",
" \n",
" | Nainen | \n",
" 2121 | \n",
" 2211 | \n",
" 2334 | \n",
" - | \n",
"
\n",
" \n",
"
\n"
],
"text/plain": [
""
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Edellisen voin toteuttaa myös pivot_table()-toiminnolla\n",
"df3 = df.pivot_table(values='palkka', index='sukup', columns='koulutus')\n",
"df3.index = sukup\n",
"df3.columns = koulutus\n",
"df3.style.format('{:.0f}', na_rep='-')"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" | | \n",
" | \n",
" palkka | \n",
" palkkat | \n",
"
\n",
" \n",
" | koulutus | \n",
" sukup | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | Peruskoulu | \n",
" Mies | \n",
" 2354 | \n",
" 1.6 | \n",
"
\n",
" \n",
" | Nainen | \n",
" 2121 | \n",
" 2.8 | \n",
"
\n",
" \n",
" | 2. aste | \n",
" Mies | \n",
" 2461 | \n",
" 1.8 | \n",
"
\n",
" \n",
" | Nainen | \n",
" 2211 | \n",
" 2.9 | \n",
"
\n",
" \n",
" | Korkeakoulu | \n",
" Mies | \n",
" 3145 | \n",
" 2.3 | \n",
"
\n",
" \n",
" | Nainen | \n",
" 2334 | \n",
" 2.7 | \n",
"
\n",
" \n",
" | Ylempi korkeakoulu | \n",
" Mies | \n",
" 5147 | \n",
" 3.0 | \n",
"
\n",
" \n",
"
\n"
],
"text/plain": [
""
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Keskiarvoja palkalle ja palkkatyytyväisyydelle koulutuksen ja sukupuolen määräämissä ryhmissä\n",
"df4 = df.groupby(['koulutus', 'sukup'])[['palkka', 'palkkat']].mean()\n",
"\n",
"# Hierarkinen (koulutus, sukupuoli) indeksi vaatii omat niksinsä tekstiarvojen sijoittamiseen\n",
"df4.index = df4.index.set_levels(koulutus, level=0)\n",
"df4.index = df4.index.set_levels(sukup, level=1)\n",
"\n",
"# Esitän palkkakeskiarvot ilman desimaaleja ja palkkatyytyväisyydet yhdellä desimaalilla\n",
"df4.style.format({'palkka':'{:.0f}', 'palkkat':'{:.1f}'})"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" | | \n",
" | \n",
" johto | \n",
" työtov | \n",
" työymp | \n",
" palkkat | \n",
" työteht | \n",
"
\n",
" \n",
" | sukup | \n",
" koulutus | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | Mies | \n",
" Peruskoulu | \n",
" 2.8 | \n",
" 4.0 | \n",
" 2.7 | \n",
" 1.6 | \n",
" 2.9 | \n",
"
\n",
" \n",
" | 2. aste | \n",
" 2.6 | \n",
" 4.2 | \n",
" 2.9 | \n",
" 1.8 | \n",
" 3.0 | \n",
"
\n",
" \n",
" | Korkeakoulu | \n",
" 3.1 | \n",
" 4.1 | \n",
" 3.5 | \n",
" 2.3 | \n",
" 3.5 | \n",
"
\n",
" \n",
" | Ylempi korkeakoulu | \n",
" 4.0 | \n",
" 4.5 | \n",
" 4.0 | \n",
" 3.0 | \n",
" 3.5 | \n",
"
\n",
" \n",
" | Nainen | \n",
" Peruskoulu | \n",
" 3.6 | \n",
" 4.2 | \n",
" 3.6 | \n",
" 2.8 | \n",
" 3.6 | \n",
"
\n",
" \n",
" | 2. aste | \n",
" 4.0 | \n",
" 4.0 | \n",
" 4.1 | \n",
" 2.9 | \n",
" 3.7 | \n",
"
\n",
" \n",
" | Korkeakoulu | \n",
" 3.4 | \n",
" 3.4 | \n",
" 4.0 | \n",
" 2.7 | \n",
" 3.3 | \n",
"
\n",
" \n",
"
\n"
],
"text/plain": [
""
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Tyytyväisyyskeskiarvoja sukupuolen ja koulutuksen mukaan\n",
"df5 = df.groupby(['sukup', 'koulutus'])[['johto', 'työtov', 'työymp', 'palkkat', 'työteht']].mean()\n",
"\n",
"# Hierarkinen (sukupuoli, koulutus) indeksi vaatii omat niksinsä tekstiarvojen sijoittamiseen\n",
"df5.index = df5.index.set_levels(sukup, level=0)\n",
"df5.index = df5.index.set_levels(koulutus, level=1)\n",
"\n",
"# Esitän tulokset yhdellä desimaalilla\n",
"df5.style.format('{:.1f}')"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" | | \n",
" palkka | \n",
"
\n",
" \n",
" \n",
" \n",
" | Mies | \n",
" 2658 | \n",
"
\n",
" \n",
" | Nainen | \n",
" 2318 | \n",
"
\n",
" \n",
"
\n"
],
"text/plain": [
""
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Keskiarvopalkat hierojaa käyttäneille sukupuolittain\n",
"df6 = df[df['hieroja']==1].groupby('sukup')['palkka'].mean()\n",
"\n",
"# Sukupuolen tekstimuotoiset arvot\n",
"df6.index = sukup\n",
"\n",
"# mean-funktiolla laskettu yksisarakkeinen tulostaulukko ei ole dataframe,\n",
"# joten muunnan sen dataframeksi\n",
"pd.DataFrame(df6).style.format('{:.0f}')"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" | | \n",
" count | \n",
" mean | \n",
" std | \n",
" min | \n",
" 25% | \n",
" 50% | \n",
" 75% | \n",
" max | \n",
"
\n",
" \n",
" \n",
" \n",
" | Mies | \n",
" 12 | \n",
" 2642 | \n",
" 905 | \n",
" 1521 | \n",
" 2134 | \n",
" 2457 | \n",
" 2974 | \n",
" 5069 | \n",
"
\n",
" \n",
" | Nainen | \n",
" 7 | \n",
" 2245 | \n",
" 382 | \n",
" 1715 | \n",
" 1969 | \n",
" 2223 | \n",
" 2574 | \n",
" 2691 | \n",
"
\n",
" \n",
"
\n"
],
"text/plain": [
""
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Palkan tunnuslukuja sukupuolittain hierojaa ja työterveyshuoltoa käyttäneillä\n",
"df7 = df[(df['hieroja']==1) & (df['työterv']==1)].groupby('sukup')['palkka'].describe()\n",
"\n",
"# Sukupuolten oikeat nimet numeroiden sijasta\n",
"df7.index = sukup\n",
"\n",
"# Esitän tulokset ilman desimaaleja\n",
"df7.style.format('{:.0f}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Lisätietoa\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.13.2"
}
},
"nbformat": 4,
"nbformat_minor": 4
}