from datetime import datetime
print(f'Päivitetty {datetime.now().date()} / Aki Taanila')
Päivitetty 2024-02-07 / Aki Taanila
Dataan voi olla tarvetta tehdä monenlaisia muunnoksia:
Tässä muistiossa käytetään pandas-kirjaston toimintoja yllä mainittujen muunnosten toteuttamiseen.
# Tuon data-analytiikan peruspaketin
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
# Jos haluan muuttaa sarakkeiden otsikoita, niin voin hyödyntää sarakeotsikoiden listaa
df.columns
Index(['nro', 'sukup', 'ikä', 'perhe', 'koulutus', 'palveluv', 'palkka', 'johto', 'työtov', 'työymp', 'palkkat', 'työteht', 'työterv', 'lomaosa', 'kuntosa', 'hieroja'], dtype='object')
Lista on tärkeä tietorakenne. Lista on aina hakasulkujen sisällä.
# Voin kopioida tähän sarakeotsikoiden listan ja muuttaa haluamani otsikot
df.columns = ['nro', 'sukupuoli', 'ikä', 'perhesuhde', 'koulutus', 'palveluv', 'palkka',
'johto', 'työtov', 'työymp', 'palkkat', 'työteht', 'työterv', 'lomaosa',
'kuntosa', 'hieroja']
# Tarkistan onnistuiko otsikoiden muuttaminen (sukupuoli, perhesuhde)
df.columns
Index(['nro', 'sukupuoli', 'ikä', 'perhesuhde', 'koulutus', 'palveluv', 'palkka', 'johto', 'työtov', 'työymp', 'palkkat', 'työteht', 'työterv', 'lomaosa', 'kuntosa', 'hieroja'], dtype='object')
Dictionary eli sanakirja on myös tärkeä tietorakenne.
# Voin vaihtaa sarakkeiden otsikoita myös rename()-toiminnolla
# Huomaa sanakirjan (dictionary) käyttö
df = df.rename(columns = {'sukupuoli':'sukup', 'perhesuhde':'perhe'})
# Tarkistan onnistuiko sarakeotsikoiden muuttaminen (sukup, perhe)
df.columns
Index(['nro', 'sukup', 'ikä', 'perhe', 'koulutus', 'palveluv', 'palkka', 'johto', 'työtov', 'työymp', 'palkkat', 'työteht', 'työterv', 'lomaosa', 'kuntosa', 'hieroja'], dtype='object')
# drop-funktiolla voin poistaa sarakkeita
# drop poistaa oletuksena rivejä (axis=0), mutta haluan poistaa sarakkeita (axis=1)
# Tallennan tämän version datasta df1-nimiseen dataframeen
df1 = df.drop(['työterv', 'lomaosa', 'kuntosa', 'hieroja'], axis=1)
df1
nro | sukup | ikä | perhe | koulutus | palveluv | palkka | johto | työtov | työymp | palkkat | työteht | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | 38 | 1 | 1.0 | 22.0 | 3587 | 3 | 3.0 | 3 | 3 | 3 |
1 | 2 | 1 | 29 | 2 | 2.0 | 10.0 | 2963 | 1 | 5.0 | 2 | 1 | 3 |
2 | 3 | 1 | 30 | 1 | 1.0 | 7.0 | 1989 | 3 | 4.0 | 1 | 1 | 3 |
3 | 4 | 1 | 36 | 2 | 1.0 | 14.0 | 2144 | 3 | 3.0 | 3 | 3 | 3 |
4 | 5 | 1 | 24 | 1 | 2.0 | 4.0 | 2183 | 2 | 3.0 | 2 | 1 | 2 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
77 | 78 | 1 | 22 | 1 | 3.0 | 0.0 | 1598 | 4 | 4.0 | 4 | 3 | 4 |
78 | 79 | 1 | 33 | 1 | 1.0 | 2.0 | 1638 | 1 | 3.0 | 2 | 1 | 2 |
79 | 80 | 1 | 27 | 1 | 2.0 | 7.0 | 2612 | 3 | 4.0 | 3 | 3 | 3 |
80 | 81 | 1 | 35 | 2 | 2.0 | 16.0 | 2808 | 3 | 4.0 | 3 | 3 | 3 |
81 | 82 | 2 | 35 | 2 | 3.0 | 15.0 | 2183 | 3 | 4.0 | 4 | 3 | 4 |
82 rows × 12 columns
Dataframen indeksi (index) on vasemmanpuoleisin sarake. Oletuksena indeksi on juokseva järjestysnumero, joka alkaa nollasta. Voin halutessani siirtää jonkin muuttujista indeksiin.
# Sarakkeen (nro) siirtäminen indeksiin
df1 = df1.set_index('nro')
df1
sukup | ikä | perhe | koulutus | palveluv | palkka | johto | työtov | työymp | palkkat | työteht | |
---|---|---|---|---|---|---|---|---|---|---|---|
nro | |||||||||||
1 | 1 | 38 | 1 | 1.0 | 22.0 | 3587 | 3 | 3.0 | 3 | 3 | 3 |
2 | 1 | 29 | 2 | 2.0 | 10.0 | 2963 | 1 | 5.0 | 2 | 1 | 3 |
3 | 1 | 30 | 1 | 1.0 | 7.0 | 1989 | 3 | 4.0 | 1 | 1 | 3 |
4 | 1 | 36 | 2 | 1.0 | 14.0 | 2144 | 3 | 3.0 | 3 | 3 | 3 |
5 | 1 | 24 | 1 | 2.0 | 4.0 | 2183 | 2 | 3.0 | 2 | 1 | 2 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
78 | 1 | 22 | 1 | 3.0 | 0.0 | 1598 | 4 | 4.0 | 4 | 3 | 4 |
79 | 1 | 33 | 1 | 1.0 | 2.0 | 1638 | 1 | 3.0 | 2 | 1 | 2 |
80 | 1 | 27 | 1 | 2.0 | 7.0 | 2612 | 3 | 4.0 | 3 | 3 | 3 |
81 | 1 | 35 | 2 | 2.0 | 16.0 | 2808 | 3 | 4.0 | 3 | 3 | 3 |
82 | 2 | 35 | 2 | 3.0 | 15.0 | 2183 | 3 | 4.0 | 4 | 3 | 4 |
82 rows × 11 columns
# Voin myös siirtää indeksiksi siirretyn takaisin tavalliseksi sarakkeeksi
df1 = df1.reset_index()
df1
nro | sukup | ikä | perhe | koulutus | palveluv | palkka | johto | työtov | työymp | palkkat | työteht | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | 38 | 1 | 1.0 | 22.0 | 3587 | 3 | 3.0 | 3 | 3 | 3 |
1 | 2 | 1 | 29 | 2 | 2.0 | 10.0 | 2963 | 1 | 5.0 | 2 | 1 | 3 |
2 | 3 | 1 | 30 | 1 | 1.0 | 7.0 | 1989 | 3 | 4.0 | 1 | 1 | 3 |
3 | 4 | 1 | 36 | 2 | 1.0 | 14.0 | 2144 | 3 | 3.0 | 3 | 3 | 3 |
4 | 5 | 1 | 24 | 1 | 2.0 | 4.0 | 2183 | 2 | 3.0 | 2 | 1 | 2 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
77 | 78 | 1 | 22 | 1 | 3.0 | 0.0 | 1598 | 4 | 4.0 | 4 | 3 | 4 |
78 | 79 | 1 | 33 | 1 | 1.0 | 2.0 | 1638 | 1 | 3.0 | 2 | 1 | 2 |
79 | 80 | 1 | 27 | 1 | 2.0 | 7.0 | 2612 | 3 | 4.0 | 3 | 3 | 3 |
80 | 81 | 1 | 35 | 2 | 2.0 | 16.0 | 2808 | 3 | 4.0 | 3 | 3 | 3 |
81 | 82 | 2 | 35 | 2 | 3.0 | 15.0 | 2183 | 3 | 4.0 | 4 | 3 | 4 |
82 rows × 12 columns
# Korjaan virheellisen iän indeksinumeron 47 mukaiselta riviltä
df1.loc[47, 'ikä'] = 42
# Tarkistan, onko indeksinumeron 47 rivillä ikä 42
df1.iloc[45:50]
nro | sukup | ikä | perhe | koulutus | palveluv | palkka | johto | työtov | työymp | palkkat | työteht | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
45 | 46 | 2 | 51 | 2 | 1.0 | 28.0 | 1989 | 3 | 3.0 | 2 | 2 | 3 |
46 | 47 | 2 | 22 | 1 | 3.0 | 21.0 | 1872 | 3 | 3.0 | 4 | 1 | 3 |
47 | 48 | 1 | 42 | 2 | 1.0 | 18.0 | 2183 | 4 | 5.0 | 4 | 1 | 3 |
48 | 49 | 1 | 27 | 2 | 2.0 | 7.0 | 2729 | 4 | 4.0 | 3 | 3 | 5 |
49 | 50 | 1 | 29 | 1 | 3.0 | 7.0 | 2340 | 3 | 4.0 | 3 | 2 | 3 |
# Luon uuden sarakkeen 'sukup_str', jossa sukupuolet tekstinä eli merkkijonoina
# Huomaa sanakirjan (dictionary) käyttö {}
df1['sukup_str'] = df1['sukup'].replace({1:'Mies', 2:'Nainen'})
df1
nro | sukup | ikä | perhe | koulutus | palveluv | palkka | johto | työtov | työymp | palkkat | työteht | sukup_str | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | 38 | 1 | 1.0 | 22.0 | 3587 | 3 | 3.0 | 3 | 3 | 3 | Mies |
1 | 2 | 1 | 29 | 2 | 2.0 | 10.0 | 2963 | 1 | 5.0 | 2 | 1 | 3 | Mies |
2 | 3 | 1 | 30 | 1 | 1.0 | 7.0 | 1989 | 3 | 4.0 | 1 | 1 | 3 | Mies |
3 | 4 | 1 | 36 | 2 | 1.0 | 14.0 | 2144 | 3 | 3.0 | 3 | 3 | 3 | Mies |
4 | 5 | 1 | 24 | 1 | 2.0 | 4.0 | 2183 | 2 | 3.0 | 2 | 1 | 2 | Mies |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
77 | 78 | 1 | 22 | 1 | 3.0 | 0.0 | 1598 | 4 | 4.0 | 4 | 3 | 4 | Mies |
78 | 79 | 1 | 33 | 1 | 1.0 | 2.0 | 1638 | 1 | 3.0 | 2 | 1 | 2 | Mies |
79 | 80 | 1 | 27 | 1 | 2.0 | 7.0 | 2612 | 3 | 4.0 | 3 | 3 | 3 | Mies |
80 | 81 | 1 | 35 | 2 | 2.0 | 16.0 | 2808 | 3 | 4.0 | 3 | 3 | 3 | Mies |
81 | 82 | 2 | 35 | 2 | 3.0 | 15.0 | 2183 | 3 | 4.0 | 4 | 3 | 4 | Nainen |
82 rows × 13 columns
# Luokkarajat ikäluokille
bins = [19, 29, 39, 49, 59, 69]
# Luon uuden sarakkeen 'ikäluokka', jossa iät luokiteltuina ikäluokkiin
df1['ikäluokka'] = pd.cut(df1['ikä'], bins=bins)
df1
# Esimerkiksi (29, 39] tarkoittaa luokkaa, johon 29-vuotias ei kuulu, mutta 39-vuotias kuuluu
nro | sukup | ikä | perhe | koulutus | palveluv | palkka | johto | työtov | työymp | palkkat | työteht | sukup_str | ikäluokka | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | 38 | 1 | 1.0 | 22.0 | 3587 | 3 | 3.0 | 3 | 3 | 3 | Mies | (29, 39] |
1 | 2 | 1 | 29 | 2 | 2.0 | 10.0 | 2963 | 1 | 5.0 | 2 | 1 | 3 | Mies | (19, 29] |
2 | 3 | 1 | 30 | 1 | 1.0 | 7.0 | 1989 | 3 | 4.0 | 1 | 1 | 3 | Mies | (29, 39] |
3 | 4 | 1 | 36 | 2 | 1.0 | 14.0 | 2144 | 3 | 3.0 | 3 | 3 | 3 | Mies | (29, 39] |
4 | 5 | 1 | 24 | 1 | 2.0 | 4.0 | 2183 | 2 | 3.0 | 2 | 1 | 2 | Mies | (19, 29] |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
77 | 78 | 1 | 22 | 1 | 3.0 | 0.0 | 1598 | 4 | 4.0 | 4 | 3 | 4 | Mies | (19, 29] |
78 | 79 | 1 | 33 | 1 | 1.0 | 2.0 | 1638 | 1 | 3.0 | 2 | 1 | 2 | Mies | (29, 39] |
79 | 80 | 1 | 27 | 1 | 2.0 | 7.0 | 2612 | 3 | 4.0 | 3 | 3 | 3 | Mies | (19, 29] |
80 | 81 | 1 | 35 | 2 | 2.0 | 16.0 | 2808 | 3 | 4.0 | 3 | 3 | 3 | Mies | (29, 39] |
81 | 82 | 2 | 35 | 2 | 3.0 | 15.0 | 2183 | 3 | 4.0 | 4 | 3 | 4 | Nainen | (29, 39] |
82 rows × 14 columns
# sukup_str on object-tyyppinen ja ikäluokka on category-tyyppinen!
df1.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 82 entries, 0 to 81 Data columns (total 14 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 sukup_str 82 non-null object 13 ikäluokka 82 non-null category dtypes: category(1), float64(3), int64(9), object(1) memory usage: 8.8+ KB
# Lasken vastaajan "kokonaistyytyväisyyden" keskiarvona tyytyväisyyksistä eri osa-alueisiin
# axis=1 tarkoittaa keskiarvojen laskemista sivusuunnassa (rivin keskiarvo)
df1['tyytyväisyys'] = df1[['johto','työtov','työymp','palkkat','työteht']].mean(axis=1)
df1[['johto', 'työtov', 'työymp', 'palkkat', 'työteht', 'tyytyväisyys']]
johto | työtov | työymp | palkkat | työteht | tyytyväisyys | |
---|---|---|---|---|---|---|
0 | 3 | 3.0 | 3 | 3 | 3 | 3.0 |
1 | 1 | 5.0 | 2 | 1 | 3 | 2.4 |
2 | 3 | 4.0 | 1 | 1 | 3 | 2.4 |
3 | 3 | 3.0 | 3 | 3 | 3 | 3.0 |
4 | 2 | 3.0 | 2 | 1 | 2 | 2.0 |
... | ... | ... | ... | ... | ... | ... |
77 | 4 | 4.0 | 4 | 3 | 4 | 3.8 |
78 | 1 | 3.0 | 2 | 1 | 2 | 1.8 |
79 | 3 | 4.0 | 3 | 3 | 3 | 3.2 |
80 | 3 | 4.0 | 3 | 3 | 3 | 3.2 |
81 | 3 | 4.0 | 4 | 3 | 4 | 3.6 |
82 rows × 6 columns
# Lasken uuden sarakkeen, jossa on käytettyjen etuisuuksien lukumäärä
df['käyttö'] = df[['työterv', 'lomaosa', 'kuntosa', 'hieroja']].count(axis=1)
df[['työterv', 'lomaosa', 'kuntosa', 'hieroja', 'käyttö']]
työterv | lomaosa | kuntosa | hieroja | käyttö | |
---|---|---|---|---|---|
0 | NaN | NaN | NaN | NaN | 0 |
1 | NaN | NaN | NaN | NaN | 0 |
2 | 1.0 | NaN | NaN | NaN | 1 |
3 | 1.0 | NaN | NaN | NaN | 1 |
4 | 1.0 | NaN | NaN | NaN | 1 |
... | ... | ... | ... | ... | ... |
77 | NaN | 1.0 | 1.0 | NaN | 2 |
78 | 1.0 | NaN | NaN | NaN | 1 |
79 | 1.0 | NaN | 1.0 | NaN | 2 |
80 | NaN | NaN | NaN | NaN | 0 |
81 | 1.0 | NaN | NaN | NaN | 1 |
82 rows × 5 columns
# Poistan rivit, joilta puuttuu koulutus, palveluv tai työtov
# Tallennan tämän version datasta df2-nimiseen dataframeen
df2 = df1.dropna(subset=['koulutus', 'palveluv', 'työtov'])
df2
nro | sukup | ikä | perhe | koulutus | palveluv | palkka | johto | työtov | työymp | palkkat | työteht | sukup_str | ikäluokka | tyytyväisyys | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | 38 | 1 | 1.0 | 22.0 | 3587 | 3 | 3.0 | 3 | 3 | 3 | Mies | (29, 39] | 3.0 |
1 | 2 | 1 | 29 | 2 | 2.0 | 10.0 | 2963 | 1 | 5.0 | 2 | 1 | 3 | Mies | (19, 29] | 2.4 |
2 | 3 | 1 | 30 | 1 | 1.0 | 7.0 | 1989 | 3 | 4.0 | 1 | 1 | 3 | Mies | (29, 39] | 2.4 |
3 | 4 | 1 | 36 | 2 | 1.0 | 14.0 | 2144 | 3 | 3.0 | 3 | 3 | 3 | Mies | (29, 39] | 3.0 |
4 | 5 | 1 | 24 | 1 | 2.0 | 4.0 | 2183 | 2 | 3.0 | 2 | 1 | 2 | Mies | (19, 29] | 2.0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
77 | 78 | 1 | 22 | 1 | 3.0 | 0.0 | 1598 | 4 | 4.0 | 4 | 3 | 4 | Mies | (19, 29] | 3.8 |
78 | 79 | 1 | 33 | 1 | 1.0 | 2.0 | 1638 | 1 | 3.0 | 2 | 1 | 2 | Mies | (29, 39] | 1.8 |
79 | 80 | 1 | 27 | 1 | 2.0 | 7.0 | 2612 | 3 | 4.0 | 3 | 3 | 3 | Mies | (19, 29] | 3.2 |
80 | 81 | 1 | 35 | 2 | 2.0 | 16.0 | 2808 | 3 | 4.0 | 3 | 3 | 3 | Mies | (29, 39] | 3.2 |
81 | 82 | 2 | 35 | 2 | 3.0 | 15.0 | 2183 | 3 | 4.0 | 4 | 3 | 4 | Nainen | (29, 39] | 3.6 |
79 rows × 15 columns
df2.shape
# Nyt datassa on enää 79 riviä (alunperin oli 82 riviä)
(79, 15)
# Halutessasi voit tallentaa muunnetun dataframen Excel-tiedostoon
df2.to_excel('muunnettu.xlsx')
Data-analytiikka Pythonilla https://tilastoapu.wordpress.com/python/