Анализ данных с pandas

Анализ данных сегодня становится все более и более популярным. Нынче аналитику данных нужно не только владеть Excel’ем, а и иметь навыки работы с языком Python как минимум. «Питон» имеет огромное множество библиотек для анализа данных, самой популярной из которых является pandas.

Введение

Pandas — библиотека для анализа и обработки данных. Работа с этой библиотекой происходит над массивами NumPy. Основные два класса в Pandas — Series и DataFrame. DataFrame содержит множество объектов Series и имеет множество методов для обработки данных в ним.

Сегодня мы рассмотрим базовые функции pandas на примере набора данных «Iris», пару способов нормализации числовых значений и визуализации данных.

Сам датасет является набором для мультиклассовой классификации, предоставленный Рональдом Фишером в 1936 году для демонстрации разработанного им метода дискретного анализа.

Начало работы

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

Для начала импортируем все необходимые модули:

Импортируем pandas, matplotlib.pyplot для построения зависимостей между признаками, numpy для работы с массивами и сам датасет.

Загружаем датасет. Не будем углубляться в его структуру, можно представить его в качестве словаря, ключи которого вы видите на экране.

Перечислим термины, которые далее будем использовать:

  • класс — определенная метка, к которому мы будем относить набор
  • признак — названия «полей» набора

Вот что значат данные метки:

  • data — двумерный массив с наборами чисел
  • target_names — названия классов, между которыми мы распределяем наборы
  • target — одномерный массив с числовыми значениями меток классов
  • feature_names — массив с названиями признаков
  • DESCR(ук. от description) — описание набора. Очень рекомендуется к прочтению.

Создаём объект DataFrame из полученного набора:

Здесь мы передаём сами значения, а в именнованом параметре columns указываем названия столбцов таблицы. Также мы воспользовались методов DataFrame.info(), который выведет нам исчерпывающую информацию о наборе. Отсюда мы можем узнать, что набор содержит 150 строк, 4 колонки, узнаем имена признаков(мы их знали изначально, однако если бы загружали датасет из .csv или .json файла, это могло бы нам пригодится). Также получим информацию, что все столбцы не содержат значений NaN(Not a Number) и принадлежат к типу float64.

Затем дополним наш DataFrame столбцом меток классов:

Здесь мы воспользовались методом DataFrame.head(), в который можно передать числовое значение(по умолчанию 5), которое указывает на кол-во строк таблицы, которые необходимо вывести на экран.

Анализ набора

Чтобы узнать, какие уникальные значения содержит отдельный столбец, воспользуемся методом Series.value_counts().

Как мы видим, к отдельному столбцу мы можем обратиться как к полю класса, если имя столбца полностью выполняет правила именования переменных Python.

Столбец Class содержит три уникальных значения, по 50 раз каждое.

Чтобы узнать минимальное и максимальное значения столбца, воспользуемся методами Series.min() и Series.max() соответственно.

Теперь построим матрицу рассеивания, используя под-модуль pandas.plotting.

Передаем в качестве аргументов сам DataFrame, прозрачность и размер фигуры.

Результат таков:

Использовав магическую команду IPython, выводим изображение прямо в JupyterNotebook.

Здесь мы видим зависимости между каждыми двумя признаками. Меня наиболее заинтересовали признаки ‘sepal length (cm)’ и ‘petal length (cm)’.

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

Результат таков:

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

Заметим, что данные точки имеют довольно маленькое значение sepal lenght(картинка слева внизу), что мы докажем, выполнив фрагмент кода ниже:

Здесь мы использовали выбор по маске(оператор == переопределён в DataFrame, возвращает массив с булевыми значениями), передав его в квадратные скобки, выбрав все строки, которые относятся к классу 0.

Как мы можем заметить, первый класс имеет довольно маленькое значение признака sepal lenght — всего 5.8, когда весь набор имеет максимальное значение, равное 7.9.

Чтобы подтвердить наши догадки, воспользуемся matplotlib. Построим такую же диаграмму, только распределим классы по цветам.

Воспользуемся функцией scatter, наносящая множество точек на плоскость. Параметр color отвечает за цвет точек, а label — за надпись, которая будет отображена в легенде. Функция legend() инициализируем саму легенду, которую с помощью параметра loc мы помещаем в левый верхний угол.

Получаем нечто такое:

И действительно, метки довольно равномерно распределены, что говорит о легкости распределения тестовых наборов среди классов.

Нормализация

Нормализация — приведение числовых значений к определённому диапазону.

Зачем это нужно? Множество метрические алгоритмы вычисляют расстояние между двумя точками с помощью эвклидой метрики.

Например, возьмём точки (1, 1) и (100, 1). Расстояние между ними будет:(

(100 — 1)^2 + (1 — 1)^2)^0.5

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

Сначала воспользуемся линейной нормализацией. Формула такова:

, где Xik — текущий элемент числового набора,

Xmin — минимальный элемент набора,

Xmax — максимальный элемент.

Для упрощения работы найдём список названий столбцов, воспользовавшись полем DataFrame.columns.values.

Возвращаясь к нашему набору, создадим новый объект DataFrame с помощью линейной нормализации:

Здесь из неизвестного только метод массива NumPy(именно в нём хранятся названия столбцов) aray.tolist(), который возвращает список значений, хранящиеся в этом массиве.

Следующий вид нормализации — нелинейная. Формула выглядит так:

, где Xc — среднее арифметическое между максимальным и минимальным значениями набора. Параметр а влияет на нелинейность.

Основная трудность реализации этой нормализации — приведение e в степень значений, находящихся в массиве, получив при этом новый массив. Можно было воспользоваться listcomp и оператором **, однако библиотека NumPy на этот счет имеет свою функцию.

Передав в функцию NumPy.exp массив, мы получим новый массив, который нам и нужен.

Новый диапазон значений первого столбца:

Заключение

Сегодня мы рассмотрели базовые функции объектов DataFrame и Series, небольшой анализ данных и два вида нормализации. Надеемся, что полученные знания пригодятся вам в дальнейшем.

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

Весь код из статьи модно найти тут.

Также рекомендую прочитать статью Базовые алгоритмы с помощью Python и подписывайтесь на мой Telegram-канал. Там еще больше полезных и интересных материалов для разработчиков