from datetime import datetime
print(f'Päivitetty {datetime.now().date()} / Aki Taanila')
Päivitetty 2024-02-08 / Aki Taanila
Frekvenssitaulukot ja ristiintaulukoinnit voin laskea crosstab-funktiolla, mutta taitavalle käyttäjälle value_counts-funktio on kätevä.
Seuraavassa esittelen value_counts niksejä.
import pandas as pd
df = pd.read_excel('https://taanila.fi/data1.xlsx')
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 82 entries, 0 to 81 Data columns (total 16 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 nro 82 non-null int64 1 sukup 82 non-null int64 2 ikä 82 non-null int64 3 perhe 82 non-null int64 4 koulutus 81 non-null float64 5 palveluv 80 non-null float64 6 palkka 82 non-null int64 7 johto 82 non-null int64 8 työtov 81 non-null float64 9 työymp 82 non-null int64 10 palkkat 82 non-null int64 11 työteht 82 non-null int64 12 työterv 47 non-null float64 13 lomaosa 20 non-null float64 14 kuntosa 9 non-null float64 15 hieroja 22 non-null float64 dtypes: float64(7), int64(9) memory usage: 10.4 KB
# Lisään dataan yhden object-tyyppisen muuttujan
df['työteht_obj'] = df['työteht'].replace({1:'Erittäin tyytymätön', 2:'Tyytymätön', 3:'Siltä väliltä',
4:'Tyytyväinen', 5:'Erittäin tyytyväinen'})
# Nyt datassa on kokonaisluku (int64), liukuluku (float64) ja object-tyyppisiä muuttujia
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 82 entries, 0 to 81 Data columns (total 17 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 nro 82 non-null int64 1 sukup 82 non-null int64 2 ikä 82 non-null int64 3 perhe 82 non-null int64 4 koulutus 81 non-null float64 5 palveluv 80 non-null float64 6 palkka 82 non-null int64 7 johto 82 non-null int64 8 työtov 81 non-null float64 9 työymp 82 non-null int64 10 palkkat 82 non-null int64 11 työteht 82 non-null int64 12 työterv 47 non-null float64 13 lomaosa 20 non-null float64 14 kuntosa 9 non-null float64 15 hieroja 22 non-null float64 16 työteht_obj 82 non-null object dtypes: float64(7), int64(9), object(1) memory usage: 11.0+ KB
# Oletuksena value_counts() järjestää frekvenssit suurimmasta pienimpään
df['työymp'].value_counts()
työymp 3 30 4 23 5 11 2 9 1 9 Name: count, dtype: int64
# Tulos ei ole dataframe, mutta to_frame() muuntaa sen dataframeksi
df['työymp'].value_counts().to_frame('f')
f | |
---|---|
työymp | |
3 | 30 |
4 | 23 |
5 | 11 |
2 | 9 |
1 | 9 |
# ascending-parametrilla järjestän frekvenssit pienimmästä suurimpaan
df['työymp'].value_counts(ascending=True).to_frame('f')
f | |
---|---|
työymp | |
2 | 9 |
1 | 9 |
5 | 11 |
4 | 23 |
3 | 30 |
# sort_index() järjestää muuttujan arvot pienimmästä suurimpaan (aakkos-/numerojärjestys)
df['työymp'].value_counts().sort_index().to_frame('f')
f | |
---|---|
työymp | |
1 | 9 |
2 | 9 |
3 | 30 |
4 | 23 |
5 | 11 |
# Myös päinvastainen järjestys on mahdollinen
df['työymp'].value_counts().sort_index(ascending=False).to_frame('f')
f | |
---|---|
työymp | |
5 | 11 |
4 | 23 |
3 | 30 |
2 | 9 |
1 | 9 |
# sort_index() laittaa object-tyypin arvot aakkosjärjestykseen
# Tämä ei yleensä ole haluttu järjestys
df['työteht_obj'].value_counts().sort_index().to_frame('f')
f | |
---|---|
työteht_obj | |
Erittäin tyytymätön | 5 |
Erittäin tyytyväinen | 8 |
Siltä väliltä | 29 |
Tyytymätön | 15 |
Tyytyväinen | 25 |
# Räätälöidyn järjestyksen saan listan ja reindex()-funktion avulla
# Tärkeää: listassa pitää olla täsmälleen samat arvot kuin muuttujalla alun perin
tyytyväisyydet = ['Erittäin tyytymätön', 'Tyytymätön', 'Siltä väliltä', 'Tyytyväinen', 'Erittäin tyytyväinen']
df['työteht_obj'].value_counts().reindex(tyytyväisyydet).to_frame('f')
f | |
---|---|
työteht_obj | |
Erittäin tyytymätön | 5 |
Tyytymätön | 15 |
Siltä väliltä | 29 |
Tyytyväinen | 25 |
Erittäin tyytyväinen | 8 |
# Voin halutessani näyttää puuttuvat arvot
df['koulutus'].value_counts(dropna=False).sort_index().to_frame('f')
f | |
---|---|
koulutus | |
1.0 | 27 |
2.0 | 30 |
3.0 | 22 |
4.0 | 2 |
NaN | 1 |
# Frekvenssit koulutus-muuttujalle
df1 = df['koulutus'].value_counts().sort_index().to_frame('f')
# Lisään prosenttisarakkeen
# Prosentit saan parametrilla normalize = True
df1['%'] = df['koulutus'].value_counts(normalize=True)*100
# Lisään muuttujan arvoille tekstimuotoiset arvot
koulutus = ['Peruskoulu', '2. aste', 'Korkeakoulu', 'Ylempi korkeakoulu']
df1.index = koulutus
# Lisään yhteensä-rivin
df1.loc['Yhteensä'] = df1.sum()
# Ulkoasun viimeistely
df1.style.format({'koulutus':'{:.0f}', '%':'{:.1f}'}, decimal=',')
f | % | |
---|---|---|
Peruskoulu | 27,000000 | 33,3 |
2. aste | 30,000000 | 37,0 |
Korkeakoulu | 22,000000 | 27,2 |
Ylempi korkeakoulu | 2,000000 | 2,5 |
Yhteensä | 81,000000 | 100,0 |
bins = [1500, 2000, 2500, 3000, 8000]
df2 = df['palkka'].value_counts(bins=bins).sort_index().to_frame('f')
df2.loc['Yhteensä'] = df2.sum()
df2
f | |
---|---|
(1499.999, 2000.0] | 19 |
(2000.0, 2500.0] | 28 |
(2500.0, 3000.0] | 22 |
(3000.0, 8000.0] | 13 |
Yhteensä | 82 |
# Ristiintaulukoinnissa hyödynnän groupby()-funktiota
# unstack siirtää sukupuolet sarakkeisiin
df3= df.groupby('sukup')['koulutus'].value_counts().sort_index().unstack('sukup')
# Koulutusten nimet aiemmin määritellystä listasta
df3.index = koulutus
df3.loc['Yhteensä'] = df3.sum()
# Sarakeotsikot
df3.columns=['Mies', 'Nainen']
# Ulkoasu ilman desimaaleja, puuttuvan arvon tilalla viiva
df3.style.format(precision=0, na_rep='-')
Mies | Nainen | |
---|---|---|
Peruskoulu | 22 | 5 |
2. aste | 23 | 7 |
Korkeakoulu | 15 | 7 |
Ylempi korkeakoulu | 2 | - |
Yhteensä | 62 | 19 |
# Ensimmäisen muuttujan frekvenssiprosentit
df4 = df['johto'].value_counts(normalize=True).sort_index().to_frame('johto')
# Lisään muiden muuttujien frekvenssiprosentit
df4['työtov'] = df['työtov'].value_counts(sort=False, normalize=True)
df4['työymp'] = df['työymp'].value_counts(sort=False, normalize=True)
df4['palkkat'] = df['palkkat'].value_counts(sort=False, normalize=True)
df4['työteht'] = df['työteht'].value_counts(sort=False, normalize=True)
# Asteikon arvot tekstimuodossa aiemmin määritellystä tyytyväisyydet-listasta
df4.index = tyytyväisyydet
df4.loc['Yhteensä'] = df4.sum()
# n-arvot sarakeotsikoihin
for var in df4.columns:
df4 = df4.rename(columns={var:f'{var}, n = {df[var].count()}'})
# Ulkoasun viimeistely
(df4*100).style.format('{:.1f} %', na_rep='-', decimal=',')
johto, n = 82 | työtov, n = 81 | työymp, n = 82 | palkkat, n = 82 | työteht, n = 82 | |
---|---|---|---|---|---|
Erittäin tyytymätön | 8,5 % | - | 11,0 % | 40,2 % | 6,1 % |
Tyytymätön | 19,5 % | 3,7 % | 11,0 % | 23,2 % | 18,3 % |
Siltä väliltä | 36,6 % | 19,8 % | 36,6 % | 23,2 % | 35,4 % |
Tyytyväinen | 28,0 % | 43,2 % | 28,0 % | 12,2 % | 30,5 % |
Erittäin tyytyväinen | 7,3 % | 33,3 % | 13,4 % | 1,2 % | 9,8 % |
Yhteensä | 100,0 % | 100,0 % | 100,0 % | 100,0 % | 100,0 % |
Data-analytiikka Pythonilla https://tilastoapu.wordpress.com/python/