Machine Learning: Как да обработим липсващи стойности?

Винаги ли получавате данните, които анализирате, в перфектен вид?

В практиката, при работа с данни, поради различни причини, те рядко са в перфектен, изчистен вид – срещат се грешни стойности, пропуски в колоните, грешен формат и др. Това налага допълнителната им обработка, за да могат данните да станат с нужното за анализа им качество и да се използват в процеса на работа.

В тази статия ще ви разкажа за един от проблемите, с който специалистите по машинно обучение се сблъскват при подготовка на данните за анализ – липсващи стойности.

Защо е важно данните да са качествени?

Когато част от данните ги няма, това предизвиква проблеми в работата на моделите за машинно обучение и се отразява негативно върху точността на получените резултати. В практиката се използват редица подходи и техники, чрез които данните да се преработят във вид, позволяващ преодоляването на тези проблеми.

Стратегии за справяне с липсващите данни

Изтриване

Радикалният подход е да се изтрият редовете или колоните, в които има липсващи стойности. Добра ли е тази идея зависи от количеството на данните (брой редове) и корелацията между характеристиките (колоните).

При по-големи извадки, например 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

Резултат:

Nofirst_namelast_nameagesexbirthCityweightheightteampoints
0JohnSmith21.0mLA86.01.88First10.0
1NaNNaNNaNNaNNaNNaNNaNNaNNaN
2PeterBrown22.0mNew York97.0NaNSecondNaN
3MariaMichaelson23.0fChicago76.01.76First25.0
4NaNNaNNaNNaNNaNNaNNaNNaNNaN
5JosieGordon22.0fNew York84.0NaNSecond34.0
6MiltonPearson21.0mNaNNaN2.10Third44.0
7HopeMarshall23.0mNew JerseyNaNNaNThirdNaN

От получения резултат веднага прави впечатление това, че има данни, които липсват в колоните birthCity, weight, height и points, a някои от редовете са изцяло без никакви данни. В този случай ще е необходимо излишните редове да бъдат премахнати.

  • Изтриване на редове без данни
df_cleaned = df.dropna(how='all')

df_cleaned

Функцията dropna() ни позволява да премахнем редове или колони, в които има липсващи стойности. Параметърът how управлява как ще става изтриването:

  • ‘all’ – изтрива се ред или колона, в която всички клетки са с NA
  • ‘any’ – изтрива ред или колона, в която има поне една клетка с NA

В нашия пример имаме 2 реда с изцяло липсващи стойности и поради тази причина how = ‘all’.

Резултат:

Nofirst_namelast_nameagesexbirthCityweightheightteampoints
0JohnSmith21.0mLA86.01.88First10.0
2PeterBrown22.0mNew York97.0NaNSecondNaN
3MariaMichaelson23.0fChicago76.01.76First25.0
5JosieGordon22.0fNew York84.0NaNSecond34.0
6MiltonPearson21.0mNaNNaN2.10Third44.0
7HopeMarshall23.0mNew JerseyNaNNaNThirdNaN
  • Заместване на липсващи стойности в birthCity с най-често срещаната (мода)

Понеже birthCity съдържа категорийни данни, е необходимо празните стойности да бъдат заместени с модата. Функцията fillna() (fill not available) на DataFrame извършва заместванията.

fill = df_cleaned['birthCity'].mode()[0]

df_cleaned['birthCity'].fillna(value=fill, inplace=True)

df_cleaned

Резултат:

Nofirst_namelast_nameagesexbirthCityweightheightteampoints
0JohnSmith21.0mLA86.01.88First10.0
2PeterBrown22.0mNew York97.0NaNSecondNaN
3MariaMichaelson23.0fChicago76.01.76First25.0
5JosieGordon22.0fNew York84.0NaNSecond34.0
6MiltonPearson21.0mNew YorkNaN2.10Third44.0
7HopeMarshall23.0mNew JerseyNaNNaNThirdNaN
  • Заместване на липсващи данни с 0 при колона points (количествена характеристика) за неявилите се участници на състезанието
df_cleaned['points'].fillna(0, inplace=True)

df_cleaned

Резултат:

Nofirst_namelast_nameagesexbirthCityweightheightteampoints
0JohnSmith21.0mLA86.01.88First10.0
2PeterBrown22.0mNew York97.0NaNSecond0.0
3MariaMichaelson23.0fChicago76.01.76First25.0
5JosieGordon22.0fNew York84.0NaNSecond34.0
6MiltonPearson21.0mNew YorkNaN2.10Third44.0
7HopeMarshall23.0mNew JerseyNaNNaNThird0.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

Резултат:

Nofirst_namelast_nameagesexbirthCityweightheightteampoints
0JohnSmith21.0mLA86.001.880000First10.0
2PeterBrown22.0mNew York97.001.913333Second0.0
3MariaMichaelson23.0fChicago76.001.760000First25.0
5JosieGordon22.0fNew York84.001.913333Second34.0
6MiltonPearson21.0mNew York85.752.100000Third44.0
7HopeMarshall23.0mNew Jersey85.751.913333Third0.0

Искате да научите повече за машинното обучение?

Включете се в курса по машинно обучение и анализ на данни с Python.

Научете повече

Автор: Десислава Христова