6 советов по работе с нулевыми значениями
Включает итерационный метод, среднее и медианное заполнение с групповым, средним и медианным заполнением
Нулевые значения — большая проблема в машинном обучении и глубоком обучении. Если вы используете sklearn, TensorFlow или любые другие пакеты машинного обучения или глубокого обучения, необходимо очищать нулевые значения перед передачей данных в среду машинного обучения или глубокого обучения. В противном случае это даст вам длинное и уродливое сообщение об ошибке.
В этой статье мы будем работать над тем, как обрабатывать нулевые значения. Сначала будут очень простые методы, и постепенно мы будем двигаться к более сложным и более эффективным способам.
Чтобы продемонстрировать обработку нулевых значений, мы будем использовать знаменитый титанический набор данных.
import pandas as pd import numpy as np import seaborn as sns titanic = sns.load_dataset("titanic") titanic
Предварительный просмотр уже показывает некоторые нулевые значения. Давайте проверим, сколько нулевых значений в каждом столбце:
titanic.isnull().sum()
Выход:
survived 0 pclass 0 sex 0 age 177 sibsp 0 parch 0 fare 0 embarked 2 class 0 who 0 adult_male 0 deck 688 embark_town 2 alive 0 alone 0 dtype: int64
В столбце age указано 177, а в столбце embark_town 2 нулевых значения. Но столбец колоды имеет наибольшее количество нулевых значений 688 из 891 строки данных. Я хотел бы полностью удалить этот столбец для машинного обучения или любого другого типа анализа данных.
Мы сосредоточимся на столбцах age и embark_town и разберемся с нулевыми значениями этих столбцов.
Давайте начнем!
Я начну с самой простой стратегии и постепенно перейду к более сложным трюкам.
1. Просто бросьте
Самая простая стратегия — удалить строки с нулевыми значениями, если у вас достаточно данных, используя этот простой код:
titanic.dropna()
Но титанический набор данных не слишком велик. На самом деле в реальном мире мы также не можем позволить себе роскошь удалять данные много раз, потому что у нас не остается достаточного количества данных после удаления всех строк с нулевыми значениями.
2. Заполнение нулями
Еще один очень легкий и простой способ. Вы можете заполнить все нулевые значения нулями, чтобы сделать процесс действительно простым. Мы можем заполнить нулевые значения в столбце возраста нулями, например:
titanic['age'].fillna(0)
Выход:
0 22.0 1 38.0 2 26.0 3 35.0 4 35.0 ... 886 27.0 887 19.0 888 0.0 889 26.0 890 32.0 Name: age, Length: 891, dtype: float64
Посмотрите на строку 888. Раньше она была нулевой, а теперь равна нулю. Это также очень наивный подход. Особенно в этом случае возраст не может быть равен нулю.
3. Заполнение вперед и назад
Это также распространенный метод заполнения нулевых значений. Прямое заполнение означает, что нулевое значение заполняется с использованием предыдущего значения в серии, а обратное заполнение означает, что нулевое значение заполняется следующим значением в серии.
titanic['age'].ffill()
Выход:
0 22.0 1 38.0 2 26.0 3 35.0 4 35.0 ... 886 27.0 887 19.0 888 19.0 889 26.0 890 32.0 Name: age, Length: 891, dtype: float64
Обратите внимание, что строка 888 теперь равна 19, как и 887.
titanic['age'].bfill()
Выход:
0 22.0 1 38.0 2 26.0 3 35.0 4 35.0 ... 886 27.0 887 19.0 888 26.0 889 26.0 890 32.0 Name: age, Length: 891, dtype: float64
Эта строка 888 взяла значение из строки 889.
4. Среднее и медианное заполнение
Я предпочитаю это в большинстве случаев, заполняя нулевые значения средним и медианным значением. Здесь я использую медиану:
titanic['age'].fillna(titanic['age'].median(), inplace = True) titanic['age']
Выход:
0 22.0 1 38.0 2 26.0 3 35.0 4 35.0 ... 886 27.0 887 19.0 888 28.0 889 26.0 890 32.0 Name: age, Length: 891, dtype: float64
Теперь нулевое значение в строке 888 равно 28, что является медианой возраста столбца.
5. Среднее и медианное заполнение с помощью Groupby
Простым подходом было указать медиану или среднее значение всего столбца. Но мне нравится немного более конкретный подход к медиане и среднему значению. Вместо того, чтобы брать медиану всего столбца возраста и заполнять все нулевые значения, заполнение нулевых значений с использованием среднего возраста каждого pclass и «живого» будет более точным.
Давайте посмотрим средний возраст «pclass» и «live», если они вообще различаются:
titanic.groupby(['pclass', 'alive'])['age'].mean()
Выход:
pclass alive 1 no 43.695312 yes 35.368197 2 no 33.544444 yes 25.901566 3 no 26.555556 yes 20.646118 Name: age, dtype: float64
Да, они сильно различаются.
Будет точнее, если мы заполним нулевые значения каждой из этих групп соответствующими средними.
titanic['age'].fillna(titanic.groupby(['pclass', 'sex'])['age'].transform('mean'))
Выход:
0 22.00 1 38.00 2 26.00 3 35.00 4 35.00 ... 886 27.00 887 19.00 888 21.75 889 26.00 890 32.00 Name: age, Length: 891, dtype: float64
Теперь строка 888 стала 21. По сравнению с 28
Вменение категориальных нулевых значений
Столбец embark_town является категориальным столбцом, и мы можем применить к нему тот же процесс, что и в предыдущем примере.
Но перед этим значения столбца embark_town нужно выразить числовыми значениями:
titanic['embark_town'] = titanic['embark_town'].astype('category') titanic['embark_town'] = titanic['embark_town'].cat.codes titanic['embark_town']
Выход:
0 2 1 0 2 2 3 2 4 2 .. 886 2 887 2 888 2 889 0 890 1 Name: embark_town, Length: 891, dtype: int8
Я сгруппирую данные по «pclass» и «alive» и заполню нулевые значения медианой.
titanic['embark_town'] = titanic['embark_town'].fillna(titanic.groupby(['pclass', 'alive'])['embark_town'].transform('median'))
6. Итеративное вменение с помощью модели машинного обучения
Это очень хороший и эффективный способ вменения нулевых значений. В этом процессе нулевые значения в каждом столбце заполняются. Каждый столбец используется как метка указанной модели машинного обучения один за другим.
Затем строки с ненулевыми значениями используются для обучения модели машинного обучения, а строки с нулевыми значениями прогнозируются с использованием этой обученной модели.
Для этой демонстрации я использую только несколько столбцов. Помните, в начале мы проверили, какие столбцы имеют нулевые значения, и увидели, что столбцы age, embark_town и deck имеют нулевые значения.
Однако в колоде столбцов было слишком много нулевых значений, и мы хотели избежать этого столбца. Но для демонстрации я добавляю столбец колоды также в набор данных titanic1.
Я использую RandomForestRegressor здесь. Вы можете использовать любую другую модель регрессии.
from sklearn.experimental import enable_iterative_imputer from sklearn.impute import IterativeImputer from sklearn.ensemble import RandomForestRegressor titanic1 = titanic[['survived', 'pclass', 'age', 'sibsp', 'fare', 'embark_town']]
Давайте сделаем вменение сейчас, и я сохраню вмененный набор данных как titanic2.
imptr = IterativeImputer(RandomForestRegressor(), max_iter=10, random_state=0) titanic2 = pd.DataFrame(imptr.fit_transform(titanic1), columns = titanic1.columns) titanic2
Возраст в строке 888 теперь 32 года!
Мы должны проверить, есть ли нулевые значения в наборе данных titanic2:
titanic2.isnull().sum()
Выход:
survived 0 pclass 0 age 0 sibsp 0 fare 0 deck 0 embark_town 0 dtype: int64
Ни в одном из столбцов больше нет нулевых значений.
Это все советы, которыми я хотел поделиться сегодня о нулевых значениях.
Заключение
Если вы хотите, вы также можете выбрать отдельные методы для отдельных столбцов. Пожалуйста, не стесняйтесь поделиться, если вы найдете какие-либо другие методы работы с нулевыми значениями более эффективными.
Пожалуйста, не стесняйтесь подписываться на меня в Twitter и Facebook page.
Подробнее Чтение
Обзор предложений и функций SQL Query
Можно использовать в качестве шпаргалки по SQLpub.towardsai.net