Datan siivoaminen Pythonilla

Voit ladata materiaalin tästä Jupyter Notebookina

Jatketaan siitä, mihin jäätiin edellisessä Jupyter notebookissa Data_exploring.

Huomattiin, että ikä ja sukupuoli -sarakkeissa on puuttuvia arvoja. Jos dataa olisi suuret määrät, voitaisiin esimerkiksi pudottaa pois ne rivit, joilla on puuttuvia arvoja missään sarakkeessa. Ensin voisi olla tietysti hyvä tarkistaa, ettei puuttuvista arvoista löyty patternia, vaan että niiden puuttuminen on satunnaista. Emme kuitenkaan mene niin pitkälle tällä kertaa.

Tutkitaanpa kyseisiä sarakkeita vielä hieman tarkemmin. Luetaan tiedosto uudelleen sisään ja tutkitaan sen jälkeen ikäsaraketta.

import pandas as pd
import numpy as np

df=pd.read_csv('generated_dataset.csv', sep=';')
df['Age'].describe()
count    952.000000
mean      33.381303
std        6.236370
min       16.000000
25%       29.000000
50%       33.000000
75%       37.000000
max       55.000000
Name: Age, dtype: float64
df['Age'].median()
33.0

Erilaisten datan tunnuslukujen lisäksi dataa voidaan myös plotata matplotlib-kirjaston avulla. Piirretään ikä-sarakkeessa olevista arvoista histogrammi.

import matplotlib.pyplot as plt

plt.xlabel('Ikä')
plt.ylabel('Lukumäärä')
plt.hist(df['Age'].dropna(), bins=32, range=(df['Age'].min(), df['Age'].max()))
plt.show()

plot

Ikädata näyttää melko normaalisti jakautuneelta. Helppo ratkaisu lisätä puuttuvat arvot on esimerkiksi korvata ne keskiarvolla tai mediaanilla, jotka tässä tapauksessa ovat siis melko samat. Valitaan näistä keskiarvo ja korvataan kaikki puuttuvat arvot sillä fillna-funktion avulla:

df['Age']=df['Age'].fillna(df['Age'].mean())

Sitten on vuorossa sukupuolisarake. Sukupuoli onkin hieman mutkikkaampi. Kyseessä on kategorinen muuttuja, joka saattaa olla pääteltävissä esimerkiksi etunimen perusteella, mutta ei aina. Etunimenkään perusteella päättelemistä ei voi automatisoida.

df['Gender'].value_counts()
Male      329
Other     316
Female    303
Name: Gender, dtype: int64

Vaikuttaa siltä, että jokaista sukupuolta on datasetissä noin kolmasosa. Tässä tapauksessa voisimme siis arpoa sukupuolen, jokaisen sukupuolen todennäköisyyden ollessa 0.3:

df['Gender']=df['Gender'].fillna(np.random.choice(['Female', 'Male', 'Other'], p=[1/3, 1/3, 1/3]))

Varmistetaan vielä, ettei datasetti sisällä enää puuttuvia arvoja:

df.isna().sum()
Student_id    0
First_name    0
Last_name     0
Points        0
Enrolled      0
Age           0
Gender        0
dtype: int64

Tässä datasetissä sukupuoli on kategorinen muuttuja. Koska useimmat koneoppimisalgoritmit haluavat vain numeerisia arvoja, kategoriset muuttujat on hyvä muuttaa numeeriksi.

Tätä varten muutetaan eri luokat omiksi sarakkeiksi, ja merkitään 0 tai 1 merkiksi siitä, kuuluuko rivin opiskelija tiettyyn luokkaan.

df=pd.get_dummies(df, columns=['Gender'])

Nyt Gender-sarakkeen arvot on muutettu numeerisiksi, voimme tarkistaa tämän ottamalla 5 ensimmäistä riviä:

df.head()
Student_id First_name Last_name Points Enrolled Age Gender_Female Gender_Male Gender_Other
0 10000 Pertti Sanchez 265 0 35.0 1 0 0
1 10001 Emily Atkins 17 1 30.0 0 0 1
2 10002 Sanna Atkins 291 1 32.0 1 0 0
3 10003 Outi Sanchez 273 1 35.0 1 0 0
4 10004 Dina Smith 273 0 34.0 1 0 0

Lisäksi voimme vielä karsia turhat sarakkeet. Jos ajatellaan, että haluaisimme muodostaa koneoppimismallin, jonka tavoitteena on ennustaa, ilmottautuuko opiskelija läsnäolevaksi, haluamme ottaa kyseisen sarakkeen omaan DataFrameen ja poistaa se nykyisestä. Yleensä puhutaan feature ja target-dataframeista:

df_target=df['Enrolled']
df_features=df.drop('Enrolled', axis=1)

Mitä muita sarakkeita uskaltaisimme poistaa? Poistamisessa tarvitsee yleensä olla todella tarkkana, ja eri muuttujien merkitsevyyden mittaamiseksi on erilaisia menetelmiä. Tässä tapauksessa menemme kuitenkin mutulla.

Nimet ovat yleensä hyviä ehdokkaita poistettavaksi, jos ne eivät ole kategorisia muuttujia tai jos ne ovat, niillä on usein myös numeerinen vastine. Esimerkiksi vaaleissa yhdellä äänestysrivillä voisi olla tieto siitä, kenelle ääni meni, mutta todennäköisempää on, että rivillä on tieto ehdokkaan numerosta. Tässä tapauksessa kyse ei ole kuitenkaan siitä, joten poistetaan etu- ja sukunimi -sarakkeet.

df_features=df_features.drop(['First_name', 'Last_name'], axis=1)

Myös erilaiset rivikohtaiset tunnisteet voidaan yleensä poistaa. Tässä tapauksessa siis opiskelijatunnus.

df_features=df_features.drop('Student_id', axis=1)

Katsotaan nyt, miltä datasetti näyttää.

df_features.head(20)
Points Age Gender_Female Gender_Male Gender_Other
0 265 35.000000 1 0 0
1 17 30.000000 0 0 1
2 291 32.000000 1 0 0
3 273 35.000000 1 0 0
4 273 34.000000 1 0 0
5 245 35.000000 1 0 0
6 230 33.381303 1 0 0
7 285 28.000000 0 0 1
8 215 25.000000 0 0 1
9 241 38.000000 0 0 1
10 153 43.000000 1 0 0
11 234 38.000000 0 0 1
12 145 37.000000 0 1 0
13 177 31.000000 0 1 0
14 300 33.000000 0 1 0
15 204 37.000000 0 0 1
16 226 34.000000 0 1 0
17 162 23.000000 0 1 0
18 51 37.000000 1 0 0
19 152 33.381303 0 0 1

Mukana on siis enää ikä, opintopisteiden määrä ja sukupuoli. Kaikki ne ovat numeerisissa muodossa, joten teoriassa tämän perusteella voitaisiin muodostaa malli koneoppimisen avulla.

Tähän teoriaosuuteen liittyy jo aiemmin ladatun tehtävän (jos et ladannut sitä vielä, voit tehdä sen tästä) osio 2.

Esimerkkivastaus tehtäviin löytyy (tästä).