Винаги ли получавате данните, които анализирате, в перфектен вид?
В практиката, при работа с данни, поради различни причини, те рядко са в перфектен, изчистен вид – срещат се грешни стойности, пропуски в колоните, грешен формат и др. Това налага допълнителната им обработка, за да могат данните да станат с нужното за анализа им качество и да се използват в процеса на работа.
В тази статия ще ви разкажа за един от проблемите, с който специалистите по машинно обучение се сблъскват при подготовка на данните за анализ – липсващи стойности.
Защо е важно данните да са качествени?
Когато част от данните ги няма, това предизвиква проблеми в работата на моделите за машинно обучение и се отразява негативно върху точността на получените резултати. В практиката се използват редица подходи и техники, чрез които данните да се преработят във вид, позволяващ преодоляването на тези проблеми.
Стратегии за справяне с липсващите данни
Изтриване
Радикалният подход е да се изтрият редовете или колоните, в които има липсващи стойности. Добра ли е тази идея зависи от количеството на данните (брой редове) и корелацията между характеристиките (колоните).
При по-големи извадки, например 5000 или повече реда, ефектът от изтриване на 20 редa няма да има толкова голямо влияние колкото например, ако извадката е с размер 50 или 100 реда.
Ако предварителният анализ на данните показва висока корелация между колона с липсващи стойности и останалите характеристики, то най-добре е тя да се остави и да се потърсят начини те да се заместят.
При липсата на прекалено много стойности в една колона (например над 50%) и слаба корелация с останалите, тя може да бъде премахната.
Заместване
По-прецизният подход е заместването на липсващите стойности, но при него изборът на подходящ метод се определя от типа на данните. Статистиката разделя данните на категорийни/качествени (пол, семейно положение и др.) и количествени/числови (възраст, размер на заплата и др.).
При категорийните данни се използва заместване с най-често срещаната стойност – мода, а при количествени данни едни от най-често използваните методи са:
- заместване със средна стойност или медиана
- запълване на празните полета с константа (например 0 или друга стойност)
- изчисляване на стойността чрез регресия
- определяне на липсващата стойност въз основа на сходство със съседни обекти
Последният от изброените методи използва алгоритъма КNN (K най-близки съседи) за групиране на обектите с идеята, че близките обекти имат сходни стойности в характеристиките.
Прилагането на някой от изброените методи се осъществява на базата на задълбочен анализ.
Как се случват нещата на практика?
За по-голяма яснота ще използваме синтетични данни за участници в състезание. Ще създадем data frame с 9 колони (first_name, last_name, age, sex, birthCity, weight, height, team и points). Ако искате да изпълните примера самостоятелно, можете да използвате Jupyter Notebook или друг подобен инструмент.
Необходимо е да импортираме библиотеките Pandas и NumPy за обработката на данни с Python.
import pandas as pd
import numpy as np
data = {'first_name': ['John', np.nan, 'Peter', 'Maria', np.nan, 'Josie', 'Milton', 'Hope'],
'last_name': ['Smith', np.nan, 'Brown', 'Michaelson', np.nan, 'Gordon','Pearson', 'Marshall'],
'age': [21, np.nan, 22, 23, np.nan, 22, 21, 23],
'sex': ['m', np.nan, 'm', 'f', np.nan, 'f', 'm', 'm'],
'birthCity': ['LA', np.nan, 'New York', 'Chicago', np.nan,
'New York', np.nan, 'New Jersey'],
'weight': [86, np.nan, 97, 76, np.nan, 84, np.nan, np.nan ],
'height': [1.88, np.nan, np.nan, 1.76, np.nan, np.nan, 2.10,
np.nan],
'team': ['First', np.nan, 'Second', 'First', np.nan, 'Second',
'Third', 'Third'],
'points': [10, np.nan, np.nan, 25, np.nan, 34, 44, np.nan ]}
df = pd.DataFrame(data)
df
Резултат:
No | first_name | last_name | age | sex | birthCity | weight | height | team | points |
---|---|---|---|---|---|---|---|---|---|
0 | John | Smith | 21.0 | m | LA | 86.0 | 1.88 | First | 10.0 |
1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
2 | Peter | Brown | 22.0 | m | New York | 97.0 | NaN | Second | NaN |
3 | Maria | Michaelson | 23.0 | f | Chicago | 76.0 | 1.76 | First | 25.0 |
4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
5 | Josie | Gordon | 22.0 | f | New York | 84.0 | NaN | Second | 34.0 |
6 | Milton | Pearson | 21.0 | m | NaN | NaN | 2.10 | Third | 44.0 |
7 | Hope | Marshall | 23.0 | m | New Jersey | NaN | NaN | Third | NaN |
От получения резултат веднага прави впечатление това, че има данни, които липсват в колоните birthCity, weight, height и points, a някои от редовете са изцяло без никакви данни. В този случай ще е необходимо излишните редове да бъдат премахнати.
- Изтриване на редове без данни
df_cleaned = df.dropna(how='all')
df_cleaned
Функцията dropna() ни позволява да премахнем редове или колони, в които има липсващи стойности. Параметърът how управлява как ще става изтриването:
- ‘all’ – изтрива се ред или колона, в която всички клетки са с NA
- ‘any’ – изтрива ред или колона, в която има поне една клетка с NA
В нашия пример имаме 2 реда с изцяло липсващи стойности и поради тази причина how = ‘all’.
Резултат:
No | first_name | last_name | age | sex | birthCity | weight | height | team | points |
---|---|---|---|---|---|---|---|---|---|
0 | John | Smith | 21.0 | m | LA | 86.0 | 1.88 | First | 10.0 |
2 | Peter | Brown | 22.0 | m | New York | 97.0 | NaN | Second | NaN |
3 | Maria | Michaelson | 23.0 | f | Chicago | 76.0 | 1.76 | First | 25.0 |
5 | Josie | Gordon | 22.0 | f | New York | 84.0 | NaN | Second | 34.0 |
6 | Milton | Pearson | 21.0 | m | NaN | NaN | 2.10 | Third | 44.0 |
7 | Hope | Marshall | 23.0 | m | New Jersey | NaN | NaN | Third | NaN |
- Заместване на липсващи стойности в birthCity с най-често срещаната (мода)
Понеже birthCity съдържа категорийни данни, е необходимо празните стойности да бъдат заместени с модата. Функцията fillna() (fill not available) на DataFrame извършва заместванията.
fill = df_cleaned['birthCity'].mode()[0]
df_cleaned['birthCity'].fillna(value=fill, inplace=True)
df_cleaned
Резултат:
No | first_name | last_name | age | sex | birthCity | weight | height | team | points |
---|---|---|---|---|---|---|---|---|---|
0 | John | Smith | 21.0 | m | LA | 86.0 | 1.88 | First | 10.0 |
2 | Peter | Brown | 22.0 | m | New York | 97.0 | NaN | Second | NaN |
3 | Maria | Michaelson | 23.0 | f | Chicago | 76.0 | 1.76 | First | 25.0 |
5 | Josie | Gordon | 22.0 | f | New York | 84.0 | NaN | Second | 34.0 |
6 | Milton | Pearson | 21.0 | m | New York | NaN | 2.10 | Third | 44.0 |
7 | Hope | Marshall | 23.0 | m | New Jersey | NaN | NaN | Third | NaN |
- Заместване на липсващи данни с 0 при колона points (количествена характеристика) за неявилите се участници на състезанието
df_cleaned['points'].fillna(0, inplace=True)
df_cleaned
Резултат:
No | first_name | last_name | age | sex | birthCity | weight | height | team | points |
---|---|---|---|---|---|---|---|---|---|
0 | John | Smith | 21.0 | m | LA | 86.0 | 1.88 | First | 10.0 |
2 | Peter | Brown | 22.0 | m | New York | 97.0 | NaN | Second | 0.0 |
3 | Maria | Michaelson | 23.0 | f | Chicago | 76.0 | 1.76 | First | 25.0 |
5 | Josie | Gordon | 22.0 | f | New York | 84.0 | NaN | Second | 34.0 |
6 | Milton | Pearson | 21.0 | m | New York | NaN | 2.10 | Third | 44.0 |
7 | Hope | Marshall | 23.0 | m | New Jersey | NaN | NaN | Third | 0.0 |
- Заместване на липсващите данни за weight и height (количествени характеристики) със средна стойност или с медиана
Дали да изберем средна стойност или медиана зависи от данните, които имаме. Когато се срещат необичайно високи/ниски стойности (outliers), по-добрият избор е медианата, като се използва функцията median() на DataFrame, а ако няма такива, е по-удачно да изберем средна стойност, която може да се изчисли с функцията mean() на DataFrame.
В нашия случай не се срещат необичайно високи или ниски стойности и ще заместим липсващите данни със средната стойност.
df_withMean = df_cleaned.copy()
df_withMean[weight].fillna(df_withMean[weight].mean(), inplace=True)
df_withMean[height].fillna(df_withMean[height].mean(), inplace=True)
df_withMean
Резултат:
No | first_name | last_name | age | sex | birthCity | weight | height | team | points |
---|---|---|---|---|---|---|---|---|---|
0 | John | Smith | 21.0 | m | LA | 86.00 | 1.880000 | First | 10.0 |
2 | Peter | Brown | 22.0 | m | New York | 97.00 | 1.913333 | Second | 0.0 |
3 | Maria | Michaelson | 23.0 | f | Chicago | 76.00 | 1.760000 | First | 25.0 |
5 | Josie | Gordon | 22.0 | f | New York | 84.00 | 1.913333 | Second | 34.0 |
6 | Milton | Pearson | 21.0 | m | New York | 85.75 | 2.100000 | Third | 44.0 |
7 | Hope | Marshall | 23.0 | m | New Jersey | 85.75 | 1.913333 | Third | 0.0 |
Искате да научите повече за машинното обучение?
Включете се в курса по машинно обучение и анализ на данни с Python.
Автор: Десислава Христова