from datetime import datetime
print(f'Päivitetty {datetime.now().date()} / Aki Taanila')
Päivitetty 2023-03-04 / Aki Taanila
Otoksessa havaitut erot ja riippuvuudet koskevat otosta.
Tärkeä kysymys: Onko otoksessa havaittu ero tai riippuvuus niin suuri, että se ei voi olla pelkkää sattumaa (otantavirhettä)? Jos ero tai riippuvuus on niin suuri, että se ei voi olla pelkkää sattumaa, niin silloin se on tilastollisesti merkitsevä ja voidaan yleistää siihen isompaan joukkoon, josta otos on poimittu.
Tilastollinen merkitsevyys selviää p-arvon avulla: p-arvo on todennäköisyys sille, että ero tai riippuvuus on pelkkää sattumaa (otantavirhettä).
Mitä pienempi p-arvo sitä merkitsevämpi ero tai riippuvuus. Vakiintuneen tavan mukaan alle 0,05 (5 %) suuruisia p-arvoja pidetään merkitsevinä.
Lue lisää https://tilastoapu.wordpress.com/2012/02/14/p-arvo/
import pandas as pd
import scipy.stats as stats
df = pd.read_excel('https://taanila.fi/data1.xlsx')
df.head()
nro | sukup | ikä | perhe | koulutus | palveluv | palkka | johto | työtov | työymp | palkkat | työteht | työterv | lomaosa | kuntosa | hieroja | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | 38 | 1 | 1.0 | 22.0 | 3587 | 3 | 3.0 | 3 | 3 | 3 | NaN | NaN | NaN | NaN |
1 | 2 | 1 | 29 | 2 | 2.0 | 10.0 | 2963 | 1 | 5.0 | 2 | 1 | 3 | NaN | NaN | NaN | NaN |
2 | 3 | 1 | 30 | 1 | 1.0 | 7.0 | 1989 | 3 | 4.0 | 1 | 1 | 3 | 1.0 | NaN | NaN | NaN |
3 | 4 | 1 | 36 | 2 | 1.0 | 14.0 | 2144 | 3 | 3.0 | 3 | 3 | 3 | 1.0 | NaN | NaN | NaN |
4 | 5 | 1 | 24 | 1 | 2.0 | 4.0 | 2183 | 2 | 3.0 | 2 | 1 | 2 | 1.0 | NaN | NaN | NaN |
Testaukseen käytettävä pearsonr-funktio antaa virheilmoituksen, jos mukana olevilla muuttujilla on puuttuvia arvoja tai jos jompikumpi muuttujista on ei-numeerinen.
# Poistan puuttuvia arvoja sisältävät rivit
df_dropna = df.dropna(subset = ['ikä', 'palkka'])
# Pearsonin korrelaatio ja 2-suuntainen p-arvo
stats.pearsonr(df_dropna['ikä'], df_dropna['palkka'])
PearsonRResult(statistic=0.2968719048961778, pvalue=0.006761514580108193)
Iän ja palkan välinen Pearsonin korrelaatio 0,30 on tilastollisesti merkitsevä (2-suuntainen p = 0,007).
# Näinkin korrelaatiokertoimen (r) ja p-arvon voi tulostaa
r, p = stats.pearsonr(df_dropna['ikä'], df_dropna['palkka'])
print(f'r = {r:.3f}, p = {p:.3f}')
r = 0.297, p = 0.007
# Spearmanin järjestyskorrelaatio ja 2-suuntainen p-arvo
r, p = stats.spearmanr(df_dropna['ikä'], df_dropna['palkka'])
print(f'r = {r:.3f}, p = {p:.3f}')
r = 0.310, p = 0.005
Iän ja palkan välinen Spearmanin järjestyskorrelaatio 0,31 on tilastollisesti merkitsevä (2- suuntainen p = 0,005).
# Khiin neliö -testi: khiin neliö, p-arvo, vapausasteet, odotetut frekvenssit
stats.chi2_contingency(pd.crosstab(df['sukup'], df['perhe']))
(3.9518615218205753, 0.046819548114598535, 1, array([[23.81707317, 39.18292683], [ 7.18292683, 11.81707317]]))
Khiin neliö -testin tulosteena on khiin neliö -testimuuttujan arvo, p-arvo, vapausasteiden lukumäärä ja hypoteeettinen ristiintaulukointi tilanteessa, jossa riippuvuutta ei olisi lainkaan.
Esimerkissämme sukupuolen ja perhesuhteen välinen riippuvuus on tilastollisesti merkitsevä (khiin neliö -testin p = 0,047).
# Jos haluat palkän p-arvon:
p = stats.chi2_contingency(pd.crosstab(df['sukup'], df['perhe']))[1]
print(f'p-arvo {p:.3f}')
p-arvo 0.047
# Poistetaan puuttuvia palkkoja sisältävät rivit
df_dropna = df.dropna(subset = ['palkka'])
# Vertailtavat ryhmät
miehet = df_dropna['palkka'][df_dropna['sukup']==1]
naiset = df_dropna['palkka'][df_dropna['sukup']==2]
print(f'Miesten keskiarvo = {miehet.mean():.0f} euroa')
print(f'Naisten keskiarvo = {naiset.mean():.0f} euroa')
# Riippumattomien otosten t-testin t ja 2-suuntainen p-arvo
# equal_var = False: ei oleteta varianssien yhtäsuuruutta
stats.ttest_ind(miehet, naiset, equal_var=False)
Miesten keskiarvo = 2664 euroa Naisten keskiarvo = 2233 euroa
Ttest_indResult(statistic=3.0597612743474714, pvalue=0.003048272029697872)
Miesten (keskiarvo 2664 euroa) ja naisten (keskiarvo 2233 euroa) palkkakeskiarvojen välillä on tilastollisesti merkitsevä ero (kahden riippumattoman otoksen 2-suuntaisen t-testin p = 0,003).
# Jos haluat pelkän p-arvon:
p = stats.ttest_ind(miehet, naiset, equal_var=False)[1]
print(f'p-arvo {p:.3f}')
p-arvo 0.003
Voidaan käyttää t-testin sijasta, jos t-testin edeltävyysehdot eivät täyty.
# Poistetaan puuttuvia palkkoja sisältävät rivit
df_dropna = df.dropna(subset = ['palkka'])
# Vertailtavat ryhmät
miehet = df_dropna['palkka'][df_dropna['sukup'] == 1] #Mies
naiset = df_dropna['palkka'][df_dropna['sukup'] == 2] #Nainen
# Mann-Whithney U -testin U ja 2-suuntainen p-arvo
stats.mannwhitneyu(miehet, naiset)
MannwhitneyuResult(statistic=786.5, pvalue=0.039222305430818116)
Mann-Whitney U -testin mukaan miesten ja naisten palkkojen välillä on tilastollisesti merkitsevä ero (p = 0,039).
# Jos haluat pelkän p-arvon:
p = stats.mannwhitneyu(miehet, naiset)[1]
print(f'p-arvo {p:.3f}')
p-arvo 0.039
# Poistetaan puuttuvia palkkoja sisältävät rivit
df_dropna = df.dropna(subset = ['palkka'])
# Vertailtavat ryhmät
k1 = df_dropna['palkka'][df_dropna['koulutus'] == 1] #peruskoulu
k2 = df_dropna['palkka'][df_dropna['koulutus'] == 2] #2. aste
k3 = df_dropna['palkka'][df_dropna['koulutus'] == 3] #korkeakoulu
k4 = df_dropna['palkka'][df_dropna['koulutus'] == 4] #ylempi korkeakoulu
# Yksisuuntaisen varianssianalyysin F ja p-arvo
stats.f_oneway(k1, k2, k3, k4)
F_onewayResult(statistic=11.675086950951924, pvalue=2.186573534680074e-06)
Palkkakeskiarvoissa on tilastollisesti merkitseviä eroja eri koulutustasojen välillä (yksisuuntaisen varianssianalyysin p < 0,001).
# Jos haluat pelkän p-arvon:
p = stats.f_oneway(k1, k2, k3, k4)[1]
print(f'p-arvo {p:.3f}')
p-arvo 0.000
Voidaan käyttää yksisuuntaisen varianssianalyysin sijasta, jos varianssianalyysin edeltävyysehdot eivät täyty.
# Poistetaan puuttuvia palkkoja sisältävät rivit
df_dropna = df.dropna(subset = ['palkka'])
# Vertailtavat ryhmät
k1 = df_dropna['palkka'][df_dropna['koulutus'] == 1] #peruskoulu
k2 = df_dropna['palkka'][df_dropna['koulutus'] == 2] #2. aste
k3 = df_dropna['palkka'][df_dropna['koulutus'] == 3] #korkeakoulu
k4 = df_dropna['palkka'][df_dropna['koulutus'] == 4] #ylempi korkeakoulu
#Kruskal-Wallis -testin H ja p-arvo
stats.kruskal(k1, k2, k3, k4)
KruskalResult(statistic=10.983022700942131, pvalue=0.011818033370911517)
Kruskall-Wallis -testin mukaan palkoissa on tilastollisesti merkitseviä eroja eri koulutustasoilla (p = 0,012).
# Jos haluat pelkän p-arvon:
p = stats.kruskal(k1, k2, k3, k4)[1]
print(f'p-arvo {p:.3f}')
p-arvo 0.012
Testien tarkemmat tiedot edeltävyysehtoineen:
https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.pearsonr.html#scipy.stats.pearsonr
https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.spearmanr.html
https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.ttest_ind.html
https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.mannwhitneyu.html
https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.f_oneway.html#scipy.stats.f_oneway
https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.kruskal.html#scipy.stats.kruskal
Lisää testejä ja tilastollisia funktioita:
https://docs.scipy.org/doc/scipy/reference/stats.html
Data-analytiikka Pythonilla: https://tilastoapu.wordpress.com/python/