You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

28 KiB

Работа с данными: Подготовка данных

 Скетчноут от (@sketchthedocs)
Подготовка данных - Скетчноут от @nitya

Тест перед лекцией

В зависимости от источника, необработанные данные могут содержать несоответствия, которые создают сложности при анализе и моделировании. Другими словами, такие данные можно классифицировать как "грязные", и их необходимо очистить. Этот урок посвящен техникам очистки и преобразования данных для решения проблем, связанных с отсутствующими, неточными или неполными данными. Темы, рассмотренные в этом уроке, будут использовать Python и библиотеку Pandas и будут продемонстрированы в ноутбуке в этом каталоге.

Важность очистки данных

  • Удобство использования и повторного использования: Когда данные правильно организованы и нормализованы, их легче искать, использовать и делиться ими с другими.

  • Согласованность: В области науки о данных часто приходится работать с несколькими наборами данных, которые необходимо объединить. Убедившись, что каждый отдельный набор данных имеет общую стандартизацию, можно гарантировать, что данные останутся полезными после их объединения в один набор.

  • Точность моделей: Очищенные данные повышают точность моделей, которые на них основаны.

Общие цели и стратегии очистки

  • Исследование набора данных: Исследование данных, которое будет рассмотрено в позднем уроке, помогает выявить данные, которые необходимо очистить. Визуальное наблюдение за значениями в наборе данных позволяет установить ожидания относительно его структуры или выявить проблемы, которые можно решить. Исследование может включать базовые запросы, визуализации и выборки.

  • Форматирование: В зависимости от источника данные могут иметь несоответствия в представлении. Это может вызывать проблемы при поиске и отображении значений, когда они видны в наборе данных, но неправильно представлены в визуализациях или результатах запросов. Общие проблемы форматирования включают устранение пробелов, корректировку дат и типов данных. Решение таких проблем обычно лежит на пользователях данных. Например, стандарты представления дат и чисел могут различаться в разных странах.

  • Дублирование: Данные с несколькими повторениями могут давать неточные результаты и обычно должны быть удалены. Это часто происходит при объединении двух или более наборов данных. Однако бывают случаи, когда дублирование в объединенных наборах данных содержит дополнительные сведения, которые могут быть полезны и должны быть сохранены.

  • Отсутствующие данные: Отсутствующие данные могут приводить к неточностям, слабым или предвзятым результатам. Иногда это можно исправить путем "перезагрузки" данных, заполнения отсутствующих значений с помощью вычислений и кода, например, на Python, или просто удаления значения и соответствующих данных. Причины отсутствия данных могут быть различными, и действия, предпринимаемые для их устранения, зависят от того, как и почему они пропали.

Исследование информации в DataFrame

Цель обучения: К концу этого раздела вы должны уверенно находить общую информацию о данных, хранящихся в pandas DataFrame.

После загрузки данных в pandas они, скорее всего, будут представлены в виде DataFrame (см. предыдущий урок для подробного обзора). Однако если набор данных в вашем DataFrame содержит 60,000 строк и 400 столбцов, с чего начать, чтобы понять, с чем вы работаете? К счастью, pandas предоставляет удобные инструменты для быстрого просмотра общей информации о DataFrame, а также первых и последних строк.

Чтобы изучить эту функциональность, мы импортируем библиотеку Python scikit-learn и используем знаковый набор данных: набор данных Iris.

import pandas as pd
from sklearn.datasets import load_iris

iris = load_iris()
iris_df = pd.DataFrame(data=iris['data'], columns=iris['feature_names'])
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
0 5.1 3.5 1.4 0.2
1 4.9 3.0 1.4 0.2
2 4.7 3.2 1.3 0.2
3 4.6 3.1 1.5 0.2
4 5.0 3.6 1.4 0.2
  • DataFrame.info: Для начала метод info() используется для вывода сводки содержимого, присутствующего в DataFrame. Давайте посмотрим на этот набор данных:
iris_df.info()
RangeIndex: 150 entries, 0 to 149
Data columns (total 4 columns):
 #   Column             Non-Null Count  Dtype  
---  ------             --------------  -----  
 0   sepal length (cm)  150 non-null    float64
 1   sepal width (cm)   150 non-null    float64
 2   petal length (cm)  150 non-null    float64
 3   petal width (cm)   150 non-null    float64
dtypes: float64(4)
memory usage: 4.8 KB

Из этого мы узнаем, что набор данных Iris содержит 150 записей в четырех столбцах без пропущенных значений. Все данные хранятся в виде 64-битных чисел с плавающей точкой.

  • DataFrame.head(): Далее, чтобы проверить фактическое содержимое DataFrame, мы используем метод head(). Давайте посмотрим, как выглядят первые несколько строк нашего iris_df:
iris_df.head()
   sepal length (cm)  sepal width (cm)  petal length (cm)  petal width (cm)
0                5.1               3.5                1.4               0.2
1                4.9               3.0                1.4               0.2
2                4.7               3.2                1.3               0.2
3                4.6               3.1                1.5               0.2
4                5.0               3.6                1.4               0.2
  • DataFrame.tail(): Напротив, чтобы проверить последние несколько строк DataFrame, мы используем метод tail():
iris_df.tail()
     sepal length (cm)  sepal width (cm)  petal length (cm)  petal width (cm)
145                6.7               3.0                5.2               2.3
146                6.3               2.5                5.0               1.9
147                6.5               3.0                5.2               2.0
148                6.2               3.4                5.4               2.3
149                5.9               3.0                5.1               1.8

Вывод: Даже просто взглянув на метаданные о содержимом DataFrame или на первые и последние значения, можно сразу получить представление о размере, форме и содержании данных, с которыми вы работаете.

Работа с отсутствующими данными

Цель обучения: К концу этого раздела вы должны знать, как заменять или удалять нулевые значения из DataFrame.

Чаще всего наборы данных, которые вы хотите использовать (или вынуждены использовать), содержат отсутствующие значения. То, как вы обрабатываете отсутствующие данные, несет с собой тонкие компромиссы, которые могут повлиять на ваш окончательный анализ и реальные результаты.

Pandas обрабатывает отсутствующие значения двумя способами. Первый вы уже видели в предыдущих разделах: NaN, или Not a Number. Это специальное значение, которое является частью спецификации IEEE для чисел с плавающей точкой и используется только для указания отсутствующих значений с плавающей точкой.

Для отсутствующих значений, кроме чисел с плавающей точкой, pandas использует объект Python None. Хотя может показаться запутанным, что вы столкнетесь с двумя различными типами значений, которые говорят по сути одно и то же, есть веские программные причины для такого выбора дизайна, и на практике это позволяет pandas предложить хороший компромисс для подавляющего большинства случаев. Тем не менее, и None, и NaN имеют ограничения, которые необходимо учитывать в отношении их использования.

Узнайте больше о NaN и None из ноутбука!

  • Обнаружение нулевых значений: В pandas методы isnull() и notnull() являются основными для обнаружения отсутствующих данных. Оба возвращают булевы маски для ваших данных. Мы будем использовать numpy для значений NaN:
import numpy as np

example1 = pd.Series([0, np.nan, '', None])
example1.isnull()
0    False
1     True
2    False
3     True
dtype: bool

Внимательно посмотрите на вывод. Вас что-то удивляет? Хотя 0 является арифметическим нулем, он, тем не менее, является вполне допустимым целым числом, и pandas рассматривает его как таковое. '' немного сложнее. Хотя мы использовали его в разделе 1 для представления пустого строкового значения, он, тем не менее, является строковым объектом, а не представлением null с точки зрения pandas.

Теперь давайте перевернем это и используем эти методы так, как вы будете использовать их на практике. Вы можете использовать булевы маски непосредственно как индекс Series или DataFrame, что может быть полезно при работе с отдельными отсутствующими (или присутствующими) значениями.

Вывод: Методы isnull() и notnull() дают схожие результаты при использовании в DataFrame: они показывают результаты и индекс этих результатов, что значительно поможет вам в работе с данными.

  • Удаление нулевых значений: Помимо идентификации отсутствующих значений, pandas предоставляет удобный способ удаления нулевых значений из Series и DataFrame. (Особенно в больших наборах данных часто более целесообразно просто удалить отсутствующие [NA] значения из анализа, чем обрабатывать их другими способами.) Чтобы увидеть это в действии, вернемся к example1:
example1 = example1.dropna()
example1
0    0
2     
dtype: object

Обратите внимание, что это должно выглядеть как ваш вывод из example3[example3.notnull()]. Разница здесь в том, что вместо индексации по маскированным значениям dropna удалил эти отсутствующие значения из Series example1.

Поскольку DataFrame имеет две измерения, он предоставляет больше возможностей для удаления данных.

example2 = pd.DataFrame([[1,      np.nan, 7], 
                         [2,      5,      8], 
                         [np.nan, 6,      9]])
example2
0 1 2
0 1.0 NaN 7
1 2.0 5.0 8
2 NaN 6.0 9

(Вы заметили, что pandas преобразовал два столбца в числа с плавающей точкой, чтобы учесть NaN?)

Вы не можете удалить одно значение из DataFrame, поэтому вам придется удалять целые строки или столбцы. В зависимости от того, что вы делаете, вы можете захотеть сделать одно или другое, и pandas предоставляет вам варианты для обоих. Поскольку в науке о данных столбцы обычно представляют переменные, а строки — наблюдения, вы, скорее всего, будете удалять строки данных; настройка по умолчанию для dropna() — удалять все строки, содержащие любые нулевые значения:

example2.dropna()
	0	1	2
1	2.0	5.0	8

Если необходимо, вы можете удалить значения NA из столбцов. Используйте axis=1, чтобы сделать это:

example2.dropna(axis='columns')
	2
0	7
1	8
2	9

Обратите внимание, что это может удалить много данных, которые вы, возможно, захотите сохранить, особенно в небольших наборах данных. Что если вы хотите удалить только строки или столбцы, содержащие несколько или даже все нулевые значения? Вы можете указать эти настройки в dropna с помощью параметров how и thresh.

По умолчанию how='any' (если вы хотите проверить это самостоятельно или увидеть, какие еще параметры есть у метода, выполните example4.dropna? в ячейке кода). Вы можете, например, указать how='all', чтобы удалять только строки или столбцы, содержащие все нулевые значения. Давайте расширим наш пример DataFrame, чтобы увидеть это в действии.

example2[3] = np.nan
example2
0 1 2 3
0 1.0 NaN 7 NaN
1 2.0 5.0 8 NaN
2 NaN 6.0 9 NaN

Параметр thresh дает вам более тонкий контроль: вы устанавливаете количество ненулевых значений, которые строка или столбец должны иметь, чтобы быть сохраненными:

example2.dropna(axis='rows', thresh=3)
	0	1	2	3
1	2.0	5.0	8	NaN

Здесь первая и последняя строки были удалены, так как они содержат только два ненулевых значения.

  • Заполнение нулевых значений: В зависимости от вашего набора данных иногда имеет смысл заполнять нулевые значения допустимыми, а не удалять их. Вы могли бы использовать isnull для этого на месте, но это может быть трудоемким, особенно если у вас много значений для заполнения. Поскольку это такая распространенная задача в науке о данных, pandas предоставляет fillna, который возвращает копию Series или DataFrame с заменой отсутствующих значений на выбранные вами. Давайте создадим еще один пример Series, чтобы увидеть, как это работает на практике.
example3 = pd.Series([1, np.nan, 2, None, 3], index=list('abcde'))
example3
a    1.0
b    NaN
c    2.0
d    NaN
e    3.0
dtype: float64

Вы можете заполнить все нулевые записи одним значением, например, 0:

example3.fillna(0)
a    1.0
b    0.0
c    2.0
d    0.0
e    3.0
dtype: float64

Вы можете заполнить вперед нулевые значения, используя последнее допустимое значение для заполнения null:

example3.fillna(method='ffill')
a    1.0
b    1.0
c    2.0
d    2.0
e    3.0
dtype: float64

Вы также можете заполнить назад, чтобы распространить следующее допустимое значение назад для заполнения null:

example3.fillna(method='bfill')
a    1.0
b    2.0
c    2.0
d    3.0
e    3.0
dtype: float64

Как вы могли догадаться, это работает так же с DataFrame, но вы также можете указать axis, вдоль которого заполнять нулевые значения. Возьмем снова ранее использованный example2:

example2.fillna(method='ffill', axis=1)
	0	1	2	3
0	1.0	1.0	7.0	7.0
1	2.0	5.0	8.0	8.0
2	NaN	6.0	9.0	9.0

Обратите внимание, что когда предыдущее значение недоступно для заполнения вперед, нулевое значение остается.

Основная мысль: Существует множество способов справиться с отсутствующими значениями в ваших наборах данных. Конкретная стратегия (удаление, замена или способ замены) должна определяться особенностями этих данных. Чем больше вы работаете с наборами данных и взаимодействуете с ними, тем лучше вы будете понимать, как справляться с отсутствующими значениями.

Удаление дублированных данных

Цель обучения: К концу этого подраздела вы должны уверенно определять и удалять дублированные значения из DataFrame.

Помимо отсутствующих данных, в реальных наборах данных вы часто будете сталкиваться с дублированными данными. К счастью, pandas предоставляет простой способ обнаружения и удаления повторяющихся записей.

  • Определение дубликатов: duplicated: Вы можете легко обнаружить дублированные значения с помощью метода duplicated в pandas, который возвращает булеву маску, указывающую, является ли запись в DataFrame дубликатом более ранней. Давайте создадим еще один пример DataFrame, чтобы увидеть это в действии.
example4 = pd.DataFrame({'letters': ['A','B'] * 2 + ['B'],
                         'numbers': [1, 2, 1, 3, 3]})
example4
letters numbers
0 A 1
1 B 2
2 A 1
3 B 3
4 B 3
example4.duplicated()
0    False
1    False
2     True
3    False
4     True
dtype: bool
  • Удаление дубликатов: drop_duplicates: просто возвращает копию данных, для которых все значения duplicated равны False:
example4.drop_duplicates()
	letters	numbers
0	A	1
1	B	2
3	B	3

Оба метода duplicated и drop_duplicates по умолчанию учитывают все столбцы, но вы можете указать, чтобы они проверяли только подмножество столбцов в вашем DataFrame:

example4.drop_duplicates(['letters'])
letters	numbers
0	A	1
1	B	2

Вывод: Удаление дублированных данных — это важная часть практически каждого проекта в области анализа данных. Дублированные данные могут исказить результаты ваших анализов и привести к неточным выводам!

🚀 Задание

Все обсуждаемые материалы предоставлены в Jupyter Notebook. Кроме того, после каждого раздела есть упражнения — попробуйте их выполнить!

Тест после лекции

Обзор и самостоятельное изучение

Существует множество способов изучения и подходов к подготовке данных для анализа и моделирования, а очистка данных — это важный этап, который требует практического опыта. Попробуйте эти задания на Kaggle, чтобы изучить техники, которые не были рассмотрены в этом уроке.

Задание

Оценка данных из формы


Отказ от ответственности:
Этот документ был переведен с помощью сервиса автоматического перевода Co-op Translator. Хотя мы стремимся к точности, пожалуйста, имейте в виду, что автоматические переводы могут содержать ошибки или неточности. Оригинальный документ на его исходном языке следует считать авторитетным источником. Для получения критически важной информации рекомендуется профессиональный перевод человеком. Мы не несем ответственности за любые недоразумения или неправильные толкования, возникшие в результате использования данного перевода.