import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.stats import norm
%matplotlib inline
Tähtitieteen tutkimusta haittasivat 1600-luvulla epätarkat mittaustulokset esimerkiksi taivaankappaleiden etäisyyksiä, sijaintia ja liikkeitä mitattaessa. Epätarkkuus johtui mm. mittauslaitteiden kehittymättömyydestä ja inhimillisistä tekijöistä. Jo Galileo Galilei tuli tulokseen, että mittausvirheet noudattavat symmetristä jakaumaa ja että pieniä virheitä esiintyy useammin kuin suuria. Gauss niminen saksalainen matemaatikko ja tähtitieteilijä esitti vuonna 1809 lausekkeen jakaumalle, jota mittausvirheet noudattivat. Nykyään kyseistä jakaumaa kutsutaan normaalijakaumaksi. Normaalijakauman lauseke määrittelee funktion, jolla on seuraavia ominaisuuksia:
x_min = -3
x_max = 3
loc = 0
scale = 1
x = np.linspace(x_min, x_max, 100)
y = norm.pdf(x, loc, scale)
plt.plot(x, y, color='C1')
plt.grid()
plt.xlim(x_min, x_max)
plt.ylim(0, 0.40)
plt.title('Normaalijakauma')
plt.xlabel('Satunnaismuuttuja x')
Text(0.5, 0, 'Satunnaismuuttuja x')
On tärkeää huomata, että normaalijakauman yhteydessä ei ole mielekästä puhua yksittäisen satunnaismuuttujan arvon todennäköisyydestä. Normaalijakaumaa noudattava satunnaismuuttujahan on jatkuva eli voi saada mitä tahansa arvoja tietyltä väliltä. Tällöin yksittäiseen arvoon liittyvä todennäköisyys on ainakin teoreettisesti ajatellen 0. Yksittäisten arvojen todennäköisyyksien sijasta on mielekästä puhua kertymätodennäköisyyksistä ja kertymätodennäköisyyksien avulla voidaan edelleen laskea erilaisten välien todennäköisyyksiä. Käytännössä normaalijakaumaa hyödynnetään kertymätodennäköisyyksien avulla. Satunnaismuuttujan arvoon x liittyvä kertymätodennäköisyys on kohdan x vasemmalle puolella oleva käyrän alapuolelle jäävä pinta-ala.
x_min = -3
x_max = 3
loc = 0
scale = 1
x = np.linspace(x_min, x_max, 100)
y = norm.pdf(x, loc, scale)
plt.plot(x, y, color='C1')
plt.grid()
plt.xlim(x_min, x_max)
plt.ylim(0, 0.40)
plt.title('Kertymätodennäköisyys')
plt.xlabel('Satunnaismuuttuja x')
x1 = -3
x2 = -1
r1 = np.linspace(x1, x2, 30)
r2 = norm.pdf(r1, loc, scale)
plt.fill_between(r1, r2, color='C0')
<matplotlib.collections.PolyCollection at 0x15610f82c08>
Esimerkki. Älykkyysosamäärää voidaan mitata tarkoitusta varten laaditulla testillä. Testin pisteytys on skaalattu sellaiseksi, että amerikkalaisten älykkyysosamäärä noudattaa likimain normaalijakaumaa N(100,16). Merkintä N(100, 16) tarkoittaa normaalijakaumaa, jonka odotusarvo on 100 ja keskihajonta 16.
loc = 100
scale = 16
norm.cdf(80, loc, scale)
0.10564977366685535
x_min = 50
x_max = 150
loc = 100
scale = 16
x = np.linspace(x_min, x_max, 100)
y = norm.pdf(x, loc, scale)
plt.plot(x, y, color='C1')
plt.grid()
plt.xlim(x_min, x_max)
plt.ylim(0, 0.030)
plt.xlabel('Älykkyysosamäärä')
x1 = 50
x2 = 80
r1 = np.linspace(x1, x2, 30)
r2 = norm.pdf(r1, loc, scale)
plt.fill_between(r1, r2, color='C0')
<matplotlib.collections.PolyCollection at 0x156120a7308>
Yllä on laskettu älykkyysosamäärään 80 liittyvä kertymätodennäköisyys. Tämän mukaan noin 10,6 % amerikkalaisista on älykkyysosamäärältään alle 80. Vastaavasti noin 89,4 % amerikkalaisista on älykkyysosamäärältään yli 80.
Todennäköisyys, että henkilön älykkyysosamäärä on täsmälleen 80, on ainakin teoreettisesti ajatellen 0. Käytännössä näin ei ehkä ole, koska älykkyysosamäärätestin pisteytys ei ole mielivaltaisen tarkkaa. Jos esimerkiksi testi pisteytetään pisteen tarkkuudella, niin todennäköisyys älykkyysosamäärälle 80 on varmasti selvästi nollasta poikkeava. Normaalijakaumaa käytettäessä kuitenkin oletetaan yksittäiseen satunnaismuuttujan arvoon liittyväksi todennäköisyydeksi 0.
Todennäköisyys, että henkilön älykkyysosamäärä on välillä 80 - 110 saadaan selville vähentämällä arvoon 110 liittyvästä kertymätodennäköisyydestä arvoon 80 liittyvä kertymätodennäköisyys:
norm.cdf(110, loc, scale) - norm.cdf(80, loc, scale)
0.6283646972844441
x_min = 50
x_max = 150
loc = 100
scale = 16
x = np.linspace(x_min, x_max, 100)
y = norm.pdf(x, loc, scale)
plt.plot(x, y, color='C1')
plt.grid()
plt.xlim(x_min, x_max)
plt.ylim(0, 0.030)
plt.xlabel('Älykkyysosamäärä')
x1 = 80
x2 = 110
r1 = np.linspace(x1, x2, 30)
r2 = norm.pdf(r1, loc, scale)
plt.fill_between(r1, r2, color='C0')
<matplotlib.collections.PolyCollection at 0x1561210f9c8>
Yllä lasketun mukaan noin 62,8 % amerikkalaisista on älykkyysosamäärältään välillä 80 - 110.
Entäpä jos halutaan tietää minkä älykkyysosamäärän ylittää älykkäin kymmenesosa amerikkalaisista? Kysytään siis satunnaismuuttujan arvoa, jonka ylittää 10 % amerikkalaisista eli kysytään satunnaismuuttujan arvoa, jonka alittaa 90 % amerikkalaisista:
norm.ppf(0.90, loc, scale)
120.5048250487136
x_min = 50
x_max = 150
loc = 100
scale = 16
x = np.linspace(x_min, x_max, 100)
y = norm.pdf(x, loc, scale)
plt.plot(x, y, color='C1')
plt.grid()
plt.xlim(x_min, x_max)
plt.ylim(0, 0.030)
plt.xlabel('Älykkyysosamäärä')
x1 = 120.5
x2 = 150
r1 = np.linspace(x1, x2, 30)
r2 = norm.pdf(r1, loc, scale)
plt.fill_between(r1, r2, color='C0')
<matplotlib.collections.PolyCollection at 0x1561217a9c8>
Yllä lasketun mukaan kyseinen älykkyysosamäärä on noin 120,5.
Esimerkki. Oletetaan, että aikaisemmista myyntitilastoista voidaan todeta, että päivittäistavaran kysynnällä lauantaisin on ollut keskiarvo 120 ja keskihajonta 15. Kauppias voi käyttää normaalijakaumaa määrittäessään seuraavan lauantain tilausmäärää kyseisen päivittäistavaran kohdalla. Oletetaan, että kauppias haluaa 95 % varmuuden tavaran riittävyydelle:
q = 0.95
loc = 120
scale = 15
norm.ppf(q, loc, scale)
144.67280440427209
x_min = 70
x_max = 170
loc = 120
scale = 15
x = np.linspace(x_min, x_max, 100)
y = norm.pdf(x, loc, scale)
plt.plot(x, y, color='C1')
plt.grid()
plt.xlim(x_min, x_max)
plt.ylim(0, 0.030)
plt.xlabel('Kysyntä')
x1 = 70
x2 = 145
r1 = np.linspace(x1, x2, 30)
r2 = norm.pdf(r1, loc, scale)
plt.fill_between(r1, r2, color='C0')
<matplotlib.collections.PolyCollection at 0x156121e84c8>
Pitää siis tilata tavaraa 145 kpl.
Esimerkki. Paperikone voidaan säätää valmistamaan eri painoisia paperilaatuja (80 grammaa/neliömetri, 85 grammaa/neliömetri jne.). Teollisesti valmistetun tuotteen ominaisuudet kuitenkin vaihtelevat monien satunnaisten tekijöiden takia. Vaikka kone on säädetty valmistamaan 80 g paperia, niin paperi ei ole kauttaaltaan 80 g. Oletetaan, että paperin tilaaja vaatii, että 90 % paperista täytyy olla yli 80 g. Minkälaista paperia paperikone pitäisi säätää valmistamaan (oletus: paperin neliömetripainon odotusarvo on säädettävissä). Oletetaan, että valmistusprosessiin ja kyseiseen paperikoneeseen liittyvä keskihajonta on 2,5 grammaa/neliömetri.
q = 0.10 #haetaan rajaa, jonka alapuolelle jää 10 %
loc = 83.21 # tähän löydetään sopiva arvo kokeilemalla
scale = 2.5
norm.ppf(q, loc, scale)
80.00612108613849
x_min = 70
x_max = 96
loc = 83.21
scale = 2.5
x = np.linspace(x_min, x_max, 100)
y = norm.pdf(x, loc, scale)
plt.plot(x, y, color='C1')
plt.grid()
plt.xlim(x_min, x_max)
plt.ylim(0, 0.20)
plt.xlabel('Paperin neliömetripaino')
x1 = 80
x2 = 96
r1 = np.linspace(x1, x2, 30)
r2 = norm.pdf(r1, loc, scale)
plt.fill_between(r1, r2, color='C0')
<matplotlib.collections.PolyCollection at 0x1561224fe48>
Kokeilemalla odotusarvon loc kohdalle erilaisia arvoja, selviää että säädettäessä odotusarvo 83,21 gramman kohdalle, 90 % paperista on yli 80 grammaista.
Edellä olleista esimerkeistä nähdään normaalijakauman soveltuvan malliksi hyvin erilaisiin käytännön tilanteisiin. Yhteistä edellä tarkastelluille satunnaismuuttujille on, että niiden arvoihin vaikuttavat monet satunnaiset tekijät. Tämä pätee yleisemminkin:
jos satunnaismuuttujan arvo määräytyy satunnaisesti lukuisten eri tekijöiden vaikutuksesta, niin muuttuja yleensä noudattaa likimain normaalijakaumaa.
Joitain kaikille normaalijakaumille päteviä todennäköisyyksiä on hyvä pitää mielessä:
loc = 100
scale = 16
print(norm.cdf(loc + scale, loc, scale) - norm.cdf(loc - scale, loc, scale))
print(norm.cdf(loc + 2*scale, loc, scale) - norm.cdf(loc - 2*scale, loc, scale))
0.6826894921370859 0.9544997361036416
x_min = 50
x_max = 150
loc = 100
scale = 16
x = np.linspace(x_min, x_max, 100)
y = norm.pdf(x, loc, scale)
plt.plot(x, y, color='C1')
plt.grid()
plt.xlim(x_min, x_max)
plt.ylim(0, 0.030)
plt.title('Kahden keskihajonnan päässä odotusarvosta noin 95 %')
plt.xlabel('Älykkyysosamäärä')
x1 = 68
x2 = 132
r1 = np.linspace(x1, x2, 30)
r2 = norm.pdf(r1, loc, scale)
plt.fill_between(r1, r2, color='C0')
<matplotlib.collections.PolyCollection at 0x156122c9a88>
Standardoitu satunnaismuuttuja eli standardipiste tarkoittaa satunnaismuuttujaa, jonka arvot on muunnettu standardia normaalijakaumaa vastaaviksi. Standardin normaalijakauman odotusarvo on 0 ja keskihajonta 1 (N(0, 1)). Satunnaismuuttujan standardoinnissa on olennaista todennäköisyyksien säilyttäminen samoina. Edellä jo todettiin, että todennäköisyydet säilyvät kunhan pysytään yhtä monen keskihajonnan päästä keskiarvosta.
Esimerkki. Jakauman N(120, 20) satunnaismuuttujan 100 standardoitu arvo on noin -1, koska 100 on yhden keskihajonnan verran odotusarvon vasemmalla puolella.
Yleinen kaava satunnaismuuttujan standardoinnille on: vähennä odotusarvo ja jaa kesihajonnalla.
Satunnaismuuttujan standardointia käytetään monissa tilastollisissa analyyseissä, mutta myös haluttaessa saada erilaisilla asteikoilla mitatut muuttujat vertailukelpoisiksi keskenään.
Standardipisteistä nähdään nopeasti esimerkiksi poikkeavat arvot. Esimerkiksi kaikki standardipistettä -2 pienemmät ja standardipistettä 2 suuremmat ovat melko harvinaisia, koska todennäköisyys näin äärimmäisille arvoille on alle 5 %.
x_min = -4
x_max = 4
loc = 0
scale = 1
x = np.linspace(x_min, x_max, 100)
y = norm.pdf(x, loc, scale)
plt.plot(x, y, color='C1')
plt.grid()
plt.xlim(x_min, x_max)
plt.ylim(0, 0.40)
plt.title('Kahden keskihajonnan päässä odotusarvosta noin 95 %')
plt.xlabel('Standardipisteet')
x1 = -2
x2 = 2
r1 = np.linspace(x1, x2, 30)
r2 = norm.pdf(r1, loc, scale)
plt.fill_between(r1, r2, color='C0')
<matplotlib.collections.PolyCollection at 0x15612333748>
Seuraavassa esimerkki standardipisteiden laskennasta:
# Datan avaus
df = pd.read_excel('https://taanila.fi/data1.xlsx')
df
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 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
77 | 78 | 1 | 22 | 1 | 3.0 | 0.0 | 1598 | 4 | 4.0 | 4 | 3 | 4 | NaN | 1.0 | 1.0 | NaN |
78 | 79 | 1 | 33 | 1 | 1.0 | 2.0 | 1638 | 1 | 3.0 | 2 | 1 | 2 | 1.0 | NaN | NaN | NaN |
79 | 80 | 1 | 27 | 1 | 2.0 | 7.0 | 2612 | 3 | 4.0 | 3 | 3 | 3 | 1.0 | NaN | 1.0 | NaN |
80 | 81 | 1 | 35 | 2 | 2.0 | 16.0 | 2808 | 3 | 4.0 | 3 | 3 | 3 | NaN | NaN | NaN | NaN |
81 | 82 | 2 | 35 | 2 | 3.0 | 15.0 | 2183 | 3 | 4.0 | 4 | 3 | 4 | 1.0 | NaN | NaN | NaN |
82 rows × 16 columns
# Lasketaan palkan standardipisteet uuteen muuttujaan
df['palkka_s'] = (df['palkka'] - df['palkka'].mean()) / df['palkka'].std()
# Nyt datassa on palkan standardipisteet sarakkeessa 'palkka_s'
df
nro | sukup | ikä | perhe | koulutus | palveluv | palkka | johto | työtov | työymp | palkkat | työteht | työterv | lomaosa | kuntosa | hieroja | palkka_s | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | 38 | 1 | 1.0 | 22.0 | 3587 | 3 | 3.0 | 3 | 3 | 3 | NaN | NaN | NaN | NaN | 1.204594 |
1 | 2 | 1 | 29 | 2 | 2.0 | 10.0 | 2963 | 1 | 5.0 | 2 | 1 | 3 | NaN | NaN | NaN | NaN | 0.469914 |
2 | 3 | 1 | 30 | 1 | 1.0 | 7.0 | 1989 | 3 | 4.0 | 1 | 1 | 3 | 1.0 | NaN | NaN | NaN | -0.676844 |
3 | 4 | 1 | 36 | 2 | 1.0 | 14.0 | 2144 | 3 | 3.0 | 3 | 3 | 3 | 1.0 | NaN | NaN | NaN | -0.494352 |
4 | 5 | 1 | 24 | 1 | 2.0 | 4.0 | 2183 | 2 | 3.0 | 2 | 1 | 2 | 1.0 | NaN | NaN | NaN | -0.448435 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
77 | 78 | 1 | 22 | 1 | 3.0 | 0.0 | 1598 | 4 | 4.0 | 4 | 3 | 4 | NaN | 1.0 | 1.0 | NaN | -1.137196 |
78 | 79 | 1 | 33 | 1 | 1.0 | 2.0 | 1638 | 1 | 3.0 | 2 | 1 | 2 | 1.0 | NaN | NaN | NaN | -1.090102 |
79 | 80 | 1 | 27 | 1 | 2.0 | 7.0 | 2612 | 3 | 4.0 | 3 | 3 | 3 | 1.0 | NaN | 1.0 | NaN | 0.056657 |
80 | 81 | 1 | 35 | 2 | 2.0 | 16.0 | 2808 | 3 | 4.0 | 3 | 3 | 3 | NaN | NaN | NaN | NaN | 0.287422 |
81 | 82 | 2 | 35 | 2 | 3.0 | 15.0 | 2183 | 3 | 4.0 | 4 | 3 | 4 | 1.0 | NaN | NaN | NaN | -0.448435 |
82 rows × 17 columns