from datetime import datetime
print(f'Päivitetty {datetime.now().date()} / Aki Taanila')
Päivitetty 2023-05-02 / Aki Taanila
Puuttuvat arvot eivät ole ongelma kuvailevassa analytiikassa. Selittävässä analytiikassakaan puuttuvista arvoista ei tarvitse huolehtia muuta kuin merkitsevyystestauksen yhteydessä. Useimmille ennakoivan analytiikan malleille puuttuvat arvot ovat myrkkyä.
Tärkeitä työkaluja puuttuvien arvojen käsittelyyn ovat isnull(), notnull(), dropna() ja fillna().
import pandas as pd
# Avaan datan
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
# isnull() kertoo mitkä ovat puuttuvia arvoja (True) ja mitkä eivät (False)
df.isnull()
nro | sukup | ikä | perhe | koulutus | palveluv | palkka | johto | työtov | työymp | palkkat | työteht | työterv | lomaosa | kuntosa | hieroja | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | False | False | False | False | False | False | False | False | False | False | False | False | True | True | True | True |
1 | False | False | False | False | False | False | False | False | False | False | False | False | True | True | True | True |
2 | False | False | False | False | False | False | False | False | False | False | False | False | False | True | True | True |
3 | False | False | False | False | False | False | False | False | False | False | False | False | False | True | True | True |
4 | False | False | False | False | False | False | False | False | False | False | False | False | False | True | True | True |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
77 | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False | True |
78 | False | False | False | False | False | False | False | False | False | False | False | False | False | True | True | True |
79 | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | True |
80 | False | False | False | False | False | False | False | False | False | False | False | False | True | True | True | True |
81 | False | False | False | False | False | False | False | False | False | False | False | False | False | True | True | True |
82 rows × 16 columns
# Puuttuvien arvojen lukumäärät
# Laskenta perustuu siihen että True=1 ja False=0
df.isnull().sum()
nro 0 sukup 0 ikä 0 perhe 0 koulutus 1 palveluv 2 palkka 0 johto 0 työtov 1 työymp 0 palkkat 0 työteht 0 työterv 35 lomaosa 62 kuntosa 73 hieroja 60 dtype: int64
# notnull() toimii päinvastoin kuin isnull()
df.notnull()
nro | sukup | ikä | perhe | koulutus | palveluv | palkka | johto | työtov | työymp | palkkat | työteht | työterv | lomaosa | kuntosa | hieroja | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | True | True | True | True | True | True | True | True | True | True | True | True | False | False | False | False |
1 | True | True | True | True | True | True | True | True | True | True | True | True | False | False | False | False |
2 | True | True | True | True | True | True | True | True | True | True | True | True | True | False | False | False |
3 | True | True | True | True | True | True | True | True | True | True | True | True | True | False | False | False |
4 | True | True | True | True | True | True | True | True | True | True | True | True | True | False | False | False |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
77 | True | True | True | True | True | True | True | True | True | True | True | True | False | True | True | False |
78 | True | True | True | True | True | True | True | True | True | True | True | True | True | False | False | False |
79 | True | True | True | True | True | True | True | True | True | True | True | True | True | False | True | False |
80 | True | True | True | True | True | True | True | True | True | True | True | True | False | False | False | False |
81 | True | True | True | True | True | True | True | True | True | True | True | True | True | False | False | False |
82 rows × 16 columns
# Arvojen lukumäärät
df.notnull().sum()
nro 82 sukup 82 ikä 82 perhe 82 koulutus 81 palveluv 80 palkka 82 johto 82 työtov 81 työymp 82 palkkat 82 työteht 82 työterv 47 lomaosa 20 kuntosa 9 hieroja 22 dtype: int64
# Poistan (dropna) rivit, joilla oli puuttuva arvo muuttujalle koulutus, palveluv tai työtov
df_dropna = df.dropna(subset = ['koulutus', 'palveluv', 'työtov'])
# Montako riviä jäi jäljelle?
df_dropna.shape[0]
79
# Korvaan (fillna) dikotomisten muuttujien puuttuvat arvot nollilla
df_fillna = df_dropna[['työterv', 'lomaosa', 'kuntosa', 'hieroja']].fillna(value=0)
df_fillna
työterv | lomaosa | kuntosa | hieroja | |
---|---|---|---|---|
0 | 0.0 | 0.0 | 0.0 | 0.0 |
1 | 0.0 | 0.0 | 0.0 | 0.0 |
2 | 1.0 | 0.0 | 0.0 | 0.0 |
3 | 1.0 | 0.0 | 0.0 | 0.0 |
4 | 1.0 | 0.0 | 0.0 | 0.0 |
... | ... | ... | ... | ... |
77 | 0.0 | 1.0 | 1.0 | 0.0 |
78 | 1.0 | 0.0 | 0.0 | 0.0 |
79 | 1.0 | 0.0 | 1.0 | 0.0 |
80 | 0.0 | 0.0 | 0.0 | 0.0 |
81 | 1.0 | 0.0 | 0.0 | 0.0 |
79 rows × 4 columns
# Voin suodattaa puuttuvat arvot näkyviin
# Suodatan ne rivit, joilla työtov-muuttuja sisältää puuttuvan arvon
df[df['työtov'].isnull()]
# työtov-muuttujalla on puuttuva arvo indeksinumeron 56 kohdalla
nro | sukup | ikä | perhe | koulutus | palveluv | palkka | johto | työtov | työymp | palkkat | työteht | työterv | lomaosa | kuntosa | hieroja | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
56 | 57 | 1 | 61 | 2 | 2.0 | 36.0 | 3119 | 2 | NaN | 2 | 1 | 5 | 1.0 | NaN | NaN | 1.0 |
# Korvaan alkuperäisessä datassa työtov-muuttujan puuttuvan arvon keskiarvolla
df['työtov'] = df['työtov'].fillna(df['työtov'].mean())
# Tarkistan miten korvaaminen onnistui (aiemmin selvisi, että puuttuva arvo on indeksinumeron 56 kohdalla)
df.loc[56, 'työtov']
4.061728395061729
Data-analytiikka Pythonilla https://tilastoapu.wordpress.com/python/