Работаем с Pandas: основные понятия и реальные данные
Разбираемся в том, как работает библиотека Pandas и проводим первый анализ данных.
Иллюстрация: Катя Павловская для Skillbox Media
Антон Яценко
Изучает Python, его библиотеки и занимается анализом данных. Любит путешествовать в горах.
Python используют для анализа данных и машинного обучения, подключая к нему различные библиотеки: Pandas, Matplotlib, NumPy, TensorFlow и другие. Каждая из них используется для решения конкретных задач.
Сегодня мы поговорим про Pandas: узнаем, для чего нужна эта библиотека, как импортировать её в Python, а также проанализируем свой первый датасет и выясним, в какой стране самый быстрый и самый медленный интернет.
Для чего нужна библиотека Pandas в Python
Pandas — главная библиотека в Python для работы с данными. Её активно используют аналитики данных и дата-сайентисты. Библиотека была создана в 2008 году компанией AQR Capital, а в 2009 году она стала проектом с открытым исходным кодом с поддержкой большого комьюнити.
Вот для каких задач используют библиотеку:
Аналитика данных: продуктовая, маркетинговая и другая. Работа с любыми данными требует анализа и подготовки: необходимо удалить или заполнить пропуски, отфильтровать, отсортировать или каким-то образом изменить данные. Pandas в Python позволяет быстро выполнить все эти действия, а в большинстве случаев ещё и автоматизировать их.
Data science и работа с большими данными. Pandas помогает подготовить и провести первичный анализ данных, чтобы потом использовать их в машинном или глубоком обучении.
Статистика. Библиотека поддерживает основные статистические методы, которые необходимы для работы с данными. Например, расчёт средних значений, их распределения по квантилям и другие.
Работа с Pandas
Для анализа данных и машинного обучения обычно используются особые инструменты: Google Colab или Jupyter Notebook. Это специализированные IDE, позволяющие работать с данными пошагово и итеративно, без необходимости создавать полноценное приложение.
В этой статье мы посмотрим на Google Colab, облачное решение для работы с данными, которое можно запустить в браузере на любом устройстве: десктопе, ноутбуке, планшете или даже смартфоне.
Каждая строчка кода на скриншоте — это одно действие, результат которого Google Colab и Jupyter Notebook сразу демонстрируют пользователю. Это удобно в задачах, связанных с аналитикой и data science.
Устанавливать Pandas при работе с Jupyter Notebook или Colab не требуется. Это стандартная библиотека, которая уже будет доступна сразу после их запуска. Останется только импортировать её в ваш код.
Series отображается в виде таблицы с индексами элементов в первом столбце и значениями во втором.
DataFrame — основной тип данных в Pandas, вокруг которого строится вся работа. Его можно представить в виде обычной таблицы с любым количеством столбцов и строк. Внутри ячеек такой «таблицы» могут быть данные самого разного типа: числовые, булевы, строковые и так далее.
У DataFrame есть и индексы строк, и индексы столбцов. Это позволяет удобно сортировать и фильтровать данные, а также быстро находить нужные ячейки.
Создадим простой DataFrame с помощью словаря и посмотрим на его отображение:
Мы видим таблицу, строки которой имеют индексы от 0 до 3, а «индексы» столбцов соответствуют их названиям. Легко заметить, что DataFrame состоит из трёх Series: «Город», «Год основания» и «Население». Оба типа индексов можно использовать для навигации по данным.
Импорт данных
Pandas позволяет импортировать данные разными способами. Например, прочесть их из словаря, списка или кортежа. Самый популярный способ — это работа с файлами .csv, которые часто применяются в анализе данных. Для импорта используют команду pd.read_csv().
read_csv имеет несколько параметров для управления импортом:
- sep — позволяет явно указать разделитель, который используется в импортируемом файле. По умолчанию значение равно ,, что соответствует разделителю данных в файлах формата .csv. Этот параметр полезен при нестандартных разделителях в исходном файле, например табуляции или точки с запятой;
- dtype — позволяет явно указать на тип данных в столбцах. Полезно в тех случаях, когда формат данных автоматически определился неверно. Например, даты часто импортируются в виде строковых переменных, хотя для них существует отдельный тип.
Подробно параметры, позволяющие настроить импорт, описаны в документации.
Давайте импортируем датасет с информацией о скорости мобильного и стационарного интернета в отдельных странах. Готовый датасет скачиваем с Kaggle. Параметры для read_csv не указываем, так как наши данные уже подготовлены для анализа.
В верхней части таблицы мы видим названия столбцов: country (страна), broadband (средняя скорость интернета) и mobile (средняя скорость мобильного интернета). Слева указаны индексы — от 0 до 176. То есть всего у нас 177 строк. В нижней части таблицы Pandas отображает и эту информацию.
Выводить таблицу полностью необязательно. Для первого знакомства с данными достаточно показать пять первых или пять последних строк. Сделать это можно с помощью df.head() или df.tail() соответственно. В скобках можно указать число строк, которое требуется указать. По умолчанию параметр равен 5.
Так намного удобнее. Мы можем сразу увидеть названия столбцов и тип данных в столбцах. Также в некоторых ячейках мы видим значение NaN — к нему мы вернёмся позже.
Изучаем данные и описываем их
Теперь нам надо изучить импортированные данные. Действовать будем пошагово.
Шаг 1. Проверяем тип данных в таблице. Это поможет понять, в каком виде представлена информация в датасете — а иногда и найти аномалии. Например, даты могут быть сохранены в виде строк, что неудобно для последующего анализа. Проверить это можно с помощью стандартного метода:
- столбец country представляет собой тип object. Это тип данных для строковых и смешанных значений;
- столбцы broadband и mobile имеют тип данных float, то есть относятся к числам с плавающей точкой.
Шаг 2. Быстро оцениваем данные и делаем предварительные выводы. Сделать это можно очень просто: для этого в Pandas существует специальный метод describe(). Он показывает среднее со стандартным отклонением, максимальные, минимальные значения переменных и их разделение по квантилям.
Посмотрим на этот метод в деле:
Пройдёмся по каждой строчке:
- count — это количество заполненных строк в каждом столбце. Мы видим, что в столбце с данными о скорости мобильного интернета есть пропуски.
- mean — среднее значение скорости обычного и мобильного интернета. Уже можно сделать вывод, что мобильный интернет в большинстве стран медленнее, чем кабельный.
- std — стандартное отклонение. Важный статистический показатель, показывающий разброс значений.
- min и max — минимальное и максимальное значение.
- 25%, 50% и 75% — значения скорости интернета по процентилям. Если не углубляться в статистику, то процентиль — это число, которое показывает распределение значений в выборке. Например, в выборке с мобильным интернетом процентиль 25% показывает, что 25% от всех значений скорости интернета меньше, чем 24,4.
Обратите внимание, что этот метод работает только для чисел. Информация для столбца с названиями стран отсутствует.
Какой вывод делаем? Проводной интернет в большинстве стран работает быстрее, чем мобильный. При этом скорость проводного интернета в 75% случаев не превышает 110 Мбит/сек, а мобильного — 69 Мбит/сек.
Шаг 3. Сортируем и фильтруем записи. В нашем датафрейме данные уже отсортированы от большего к меньшему по скорости проводного интернета. Попробуем найти страну с наилучшим мобильным интернетом. Для этого используем стандартный метод sort_values, который принимает два параметра:
- название столбца, по которому происходит сортировка, — обязательно должно быть заключено в одинарные или двойные кавычки;
- параметр ascending= — указывает на тип сортировки. Если мы хотим отсортировать значения от большего к меньшему, то параметру присваиваем False. Для сортировки от меньшего к большему используем True.
Перейдём к коду:
Теперь рейтинг стран другой — пятёрка лидеров поменялась (потому что мы отсортировали данные по другому значению). Мы выяснили, что самый быстрый мобильный интернет в ОАЭ.
Но есть нюанс. Если вернуться к первоначальной таблице, отсортированной по скорости проводного интернета, можно заметить, что у лидера — Монако — во втором столбце написано NaN. NaN в Python указывает на отсутствие данных. Поэтому мы не знаем скорость мобильного интернета в Монако из этого датасета и не можем сделать однозначный вывод о лидерах в мире мобильной связи.
Попробуем отфильтровать значения, убрав страны с неизвестной скоростью мобильного интернета, и посмотрим на худшие по показателю страны (если оставить NaN, он будет засорять «дно» таблицы и увидеть реальные значения по самому медленному мобильному интернету будет сложновато).
В Pandas существуют различные способы фильтрации для удаления NaN. Мы воспользуемся методом dropna(), который удаляет все строки с пропусками. Важно, что удаляется полностью строка, содержащая NaN, а не только ячейки с пропущенными значениями в столбце с пропусками.
Количество строк в датафрейме при удалении пустых данных уменьшилось до 136. Если вернуться ко второму шагу, то можно увидеть, что это соответствует количеству заполненных строк в столбце mobile в начальном датафрейме.
Сохраним результат в новый датафрейм и назовём его df_without_nan. Изначальный DataFrame стараемся не менять, так как он ещё может нам понадобиться.
Худший мобильный интернет в Афганистане с небольшим отставанием от Палестины и Венесуэлы.
Что дальше?
Pandas в Python — мощная библиотека для анализа данных. В этой статье мы прошли по базовым операциям. Подробнее про работу библиотеки можно узнать в документации. Углубиться в работу с библиотекой можно благодаря специализированным книгам:
- «Изучаем pandas. Высокопроизводительная обработка и анализ данных в Python» Майкла Хейдта и Артёма Груздева;
- «Thinking in Pandas: How to Use the Python Data Analysis Library the Right Way», Hannah Stepanek;
- «Hands-On Data Analysis with Pandas: Efficiently perform data collection, wrangling, analysis, and visualization using Python», Stefanie Molin.
Читайте также:
- Библиотеки в программировании: для чего нужны и какими бывают
- Тест: угадайте, где эзотерические языки программирования, а где — нет
- Как начать программировать на Python: экспресс-гайд
Структуры данных в pandas / pd 2
Ядром pandas являются две структуры данных, в которых происходят все операции:
Series — это структура, используемая для работы с последовательностью одномерных данных, а Dataframe — более сложная и подходит для нескольких измерений.
Пусть они и не являются универсальными для решения всех проблем, предоставляют отличный инструмент для большинства приложений. При этом их легко использовать, а множество более сложных структур можно упросить до одной из этих двух.
Однако особенности этих структур основаны на одной черте — интеграции в их структуру объектов index и labels (метки). С их помощью структурами становится очень легко манипулировать.
Series (серии)
Series — это объект библиотеки pandas, спроектированный для представления одномерных структур данных, похожих на массивы, но с дополнительными возможностями. Его структура проста, ведь он состоит из двух связанных между собой массивов. Основной содержит данные (данные любого типа NumPy), а в дополнительном, index , хранятся метки.
Создание объекта Series
Для создания объекта Series с предыдущего изображения необходимо вызвать конструктор Series() и передать в качестве аргумента массив, содержащий значения, которые необходимо включить.
>>> s = pd.Series([12,-4,7,9]) >>> s 0 12 1 -4 2 7 3 9 dtype: int64
Как можно увидеть по выводу, слева отображаются значения индексов, а справа — сами значения (данные).
Если не определить индекс при объявлении объекта, метки будут соответствовать индексам (положению в массиве) элементов объекта Series .
Однако лучше создавать Series , используя метки с неким смыслом, чтобы в будущем отделять и идентифицировать данные вне зависимости от того, в каком порядке они хранятся.
В таком случае необходимо будет при вызове конструктора включить параметр index и присвоить ему массив строк с метками.
>>> s = pd.Series([12,-4,7,9], index=['a','b','c','d']) >>> s a 12 b -4 c 7 d 9 dtype: int64
Если необходимо увидеть оба массива, из которых состоит структура, можно вызвать два атрибута: index и values .
>>> s.values array([12, -4, 7, 9], dtype=int64) >>> s.index Index(['a', 'b', 'c', 'd'], dtype='object')
Выбор элементов по индексу или метке
Выбирать отдельные элементы можно по принципу обычных массивов numpy, используя для этого индекс.
>>> s[2] 7
Или же можно выбрать метку, соответствующую положению индекса.
>>> s['b'] -4
Таким же образом можно выбрать несколько элементов массива numpy с помощью следующей команды:
>>> s[0:2] a 12 b -4 dtype: int64
В этом случае можно использовать соответствующие метки, но указать их список в массиве.
>>> s[['b','c']] b -4 c 7 dtype: int64
Присваивание значений элементам
Понимая как выбирать отдельные элементы, важно знать и то, как присваивать им новые значения. Можно делать это по индексу или по метке.
>>> s[1] = 0 >>> s a 12 b 0 c 7 d 9 dtype: int64
>>> s['b'] = 1 >>> s a 12 b 1 c 7 d 9 dtype: int64
Создание Series из массивов NumPy
Новый объект Series можно создать из массивов NumPy и уже существующих Series .
>>> arr = np.array([1,2,3,4]) >>> s3 = pd.Series(arr) >>> s3 0 1 1 2 2 3 3 4 dtype: int32
>>> s4 = pd.Series(s) >>> s4 a 12 b 1 c 7 d 9 dtype: int64
Важно запомнить, что значения в массиве NumPy или оригинальном объекте Series не копируются, а передаются по ссылке. Это значит, что элементы объекта вставляются динамически в новый Series . Если меняется оригинальный объект, то меняются и его значения в новом.
>>> s3 0 1 1 2 2 3 3 4 dtype: int32
>>> arr[2] = -2 >>> s3 0 1 1 2 2 -2 3 4 dtype: int32
На этом примере можно увидеть, что при изменении третьего элемента массива arr , меняется соответствующий элемент и в s3 .
Фильтрация значений
Благодаря тому что основной библиотекой в pandas является NumPy, многие операции, применяемые к массивам NumPy, могут быть использованы и в случае с Series . Одна из таких — фильтрация значений в структуре данных с помощью условий.
Например, если нужно узнать, какие элементы в Series больше 8, то можно написать следующее:
>>> s[s > 8] a 12 d 9 dtype: int64
Операции и математические функции
Другие операции, такие как операторы ( +, -, * и / ), а также математические функции, работающие с массивами NumPy, могут использоваться и для Series .
Для операторов можно написать простое арифметическое уравнение.
>>> s / 2 a 6.0 b 0.5 c 3.5 d 4.5 dtype: float64
Но в случае с математическими функциями NumPy необходимо указать функцию через np , а Series передать в качестве аргумента.
>>> np.log(s) a 2.484907 b 0.000000 c 1.945910 d 2.197225 dtype: float64
Количество значений
В Series часто встречаются повторения значений. Поэтому важно иметь информацию, которая бы указывала на то, есть ли дубликаты или конкретное значение в объекте.
Так, можно объявить Series , в котором будут повторяющиеся значения.
>>> serd = pd.Series([1,0,2,1,2,3], index=['white','white','blue','green',' green','yellow']) >>> serd white 1 white 0 blue 2 green 1 green 2 yellow 3 dtype: int64
Чтобы узнать обо всех значениях в Series , не включая дубли, можно использовать функцию unique() . Возвращаемое значение — массив с уникальными значениями, необязательно в том же порядке.
>>> serd.unique() array([1, 0, 2, 3], dtype=int64)
На unique() похожа функция value_counts() , которая возвращает не только уникальное значение, но и показывает, как часто элементы встречаются в Series .
>>> serd.value_counts() 2 2 1 2 3 1 0 1 dtype: int64
Наконец, isin() показывает, есть ли элементы на основе списка значений. Она возвращает булевые значения, которые очень полезны при фильтрации данных в Series или в колонке Dataframe .
>>> serd.isin([0,3]) white False white True blue False green False green False yellow True dtype: bool
>>> serd[serd.isin([0,3])] white 0 yellow 3 dtype: int64
Значения NaN
В предыдущем примере мы попробовали получить логарифм отрицательного числа и результатом стало значение NaN . Это значение (Not a Number) используется в структурах данных pandas для обозначения наличия пустого поля или чего-то, что невозможно обозначить в числовой форме.
Как правило, NaN — это проблема, для которой нужно найти определенное решение, особенно при работе с анализом данных. Эти данные часто появляются при извлечении информации из непроверенных источников или когда в самом источнике недостает данных. Также значения NaN могут генерироваться в специальных случаях, например, при вычислении логарифмов для отрицательных значений, в случае исключений при вычислениях или при использовании функций. Есть разные стратегии работы со значениями NaN .
Несмотря на свою «проблемность» pandas позволяет явно определять NaN и добавлять это значение в структуры, например, в Series . Для этого внутри массива достаточно ввести np.NaN в том месте, где требуется определить недостающее значение.
>>> s2 = pd.Series([5,-3,np.NaN,14]) >>> s2 0 5.0 1 -3.0 2 NaN 3 14.0 dtype: float64
Функции isnull() и notnull() очень полезны для определения индексов без значения.
>>> s2.isnull() 0 False 1 False 2 True 3 False dtype: bool
>>> s2.notnull() 0 True 1 True 2 False 3 True dtype: bool
Они возвращают два объекта Series с булевыми значениями, где True указывает на наличие значение, а NaN — на его отсутствие. Функция isnull() возвращает True для значений NaN в Series , а notnull() — True в тех местах, где значение не равно NaN . Эти функции часто используются в фильтрах для создания условий.
>>> s2[s2.notnull()] 0 5.0 1 -3.0 3 14.0 dtype: float64
s2[s2.isnull()] 2 NaN dtype: float64
Series из словарей
Series можно воспринимать как объект dict (словарь). Эта схожесть может быть использована на этапе объявления объекта. Даже создавать Series можно на основе существующего dict .
>>> mydict = 'red': 2000, 'blue': 1000, 'yellow': 500, 'orange': 1000> >>> myseries = pd.Series(mydict) >>> myseries blue 1000 orange 1000 red 2000 yellow 500 dtype: int64
На этом примере можно увидеть, что массив индексов заполнен ключами, а данные — соответствующими значениями. В таком случае соотношение будет установлено между ключами dict и метками массива индексов. Если есть несоответствие, pandas заменит его на NaN .
>>> colors = ['red','yellow','orange','blue','green'] >>> myseries = pd.Series(mydict, index=colors) >>> myseries red 2000.0 yellow 500.0 orange 1000.0 blue 1000.0 green NaN dtype: float64
Операции с сериями
Вы уже видели, как выполнить арифметические операции на объектах Series и скалярных величинах. То же возможно и для двух объектов Series , но в таком случае в дело вступают и метки.
Одно из главных достоинств этого типа структур данных в том, что он может выравнивать данные, определяя соответствующие метки.
В следующем примере добавляются два объекта Series , у которых только некоторые метки совпадают.
>>> mydict2 = 'red':400,'yellow':1000,'black':700> >>> myseries2 = pd.Series(mydict2) >>> myseries + myseries2 black NaN blue NaN green NaN orange NaN red 2400.0 yellow 1500.0 dtype: float64
Новый объект получает только те элементы, где метки совпали. Все остальные тоже присутствуют, но со значением NaN.
DataFrame (датафрейм)
Dataframe — это табличная структура данных, напоминающая таблицы из Microsoft Excel. Ее главная задача — позволить использовать многомерные Series . Dataframe состоит из упорядоченной коллекции колонок, каждая из которых содержит значение разных типов (числовое, строковое, булевое и так далее).
В отличие от Series у которого есть массив индексов с метками, ассоциированных с каждым из элементов, Dataframe имеет сразу два таких. Первый ассоциирован со строками (рядами) и напоминает таковой из Series . Каждая метка ассоциирована со всеми значениями в ряду. Второй содержит метки для каждой из колонок.
Dataframe можно воспринимать как dict , состоящий из Series , где ключи — названия колонок, а значения — объекты Series , которые формируют колонки самого объекта Dataframe . Наконец, все элементы в каждом объекте Series связаны в соответствии с массивом меток, называемым index .
Создание Dataframe
Простейший способ создания Dataframe — передать объект dict в конструктор DataFrame() . Объект dict содержит ключ для каждой колонки, которую требуется определить, а также массив значений для них.
Если объект dict содержит больше данных, чем требуется, можно сделать выборку. Для этого в конструкторе Dataframe нужно определить последовательность колонок с помощью параметра column . Колонки будут созданы в заданном порядке вне зависимости от того, как они расположены в объекте dict .
>> data = 'color' : ['blue', 'green', 'yellow', 'red', 'white'], 'object' : ['ball', 'pen', 'pencil', 'paper', 'mug'], 'price' : [1.2, 1.0, 0.6, 0.9, 1.7]> >>> frame = pd.DataFrame(data) >>> frame
color | object | price | |
---|---|---|---|
0 | blue | ball | 1.2 |
1 | green | pen | 1.0 |
2 | yellow | pencil | 0.6 |
3 | red | paper | 0.9 |
4 | white | mug | 1.7 |
Даже для объектов Dataframe если метки явно не заданы в массиве index , pandas автоматически присваивает числовую последовательность, начиная с нуля. Если же индексам Dataframe нужно присвоить метки, необходимо использовать параметр index и присвоить ему массив с метками.
>>> frame2 = pd.DataFrame(data, columns=['object', 'price']) >>> frame2
object | price | |
---|---|---|
0 | ball | 1.2 |
1 | pen | 1.0 |
2 | pencil | 0.6 |
3 | paper | 0.9 |
4 | mug | 1.7 |
Теперь, зная о параметрах index и columns , проще использовать другой способ определения Dataframe . Вместо использования объекта dict можно определить три аргумента в конструкторе в следующем порядке: матрицу данных, массив значений для параметра index и массив с названиями колонок для параметра columns .
В большинстве случаев простейший способ создать матрицу значений — использовать np.arrange(16).reshape((4,4)) . Это формирует матрицу размером 4х4 из чисел от 0 до 15.
>>> frame3 = pd.DataFrame(np.arange(16).reshape((4,4)), ... index=['red', 'blue', 'yellow', 'white'], ... columns=['ball', 'pen', 'pencil', 'paper']) >>> frame3
Выбор элементов
Если нужно узнать названия всех колонок Dataframe , можно вызвать атрибут columns для экземпляра объекта.
>>> frame.columns Index(['color', 'object', 'price'], dtype='object')
То же можно проделать и для получения списка индексов.
>>> frame.index RangeIndex(start=0, stop=5, step=1)
Весь же набор данных можно получить с помощью атрибута values .
>>> frame.values array([['blue', 'ball', 1.2], ['green', 'pen', 1.0], ['yellow', 'pencil', 0.6], ['red', 'paper', 0.9], ['white', 'mug', 1.7]], dtype=object)
Указав в квадратных скобках название колонки, можно получить значений в ней.
>>> frame['price'] 0 1.2 1 1.0 2 0.6 3 0.9 4 1.7 Name: price, dtype: float64
Возвращаемое значение — объект Series . Название колонки можно использовать и в качестве атрибута.
>>> frame.price 0 1.2 1 1.0 2 0.6 3 0.9 4 1.7 Name: price, dtype: float64
Для строк внутри Dataframe используется атрибут loc со значением индекса нужной строки.
>>> frame.loc[2] color yellow object pencil price 0.6 Name: 2, dtype: object
Возвращаемый объект — это снова Series , где названия колонок — это уже метки массива индексов, а значения — данные Series .
Для выбора нескольких строк можно указать массив с их последовательностью.
>>> frame.loc[[2,4]]
color | object | price | |
---|---|---|---|
2 | yellow | pencil | 0.6 |
4 | white | mug | 1.7 |
Если необходимо извлечь часть Dataframe с конкретными строками, для этого можно использовать номера индексов. Она выведет данные из соответствующей строки и названия колонок.
>>> frame[0:1]
color | object | price | |
---|---|---|---|
2 | yellow | pencil | 0.6 |
4 | white | mug | 1.7 |
Возвращаемое значение — объект Dataframe с одной строкой. Если нужно больше одной строки, необходимо просто указать диапазон.
>>> frame[1:3]
color | object | price | |
---|---|---|---|
0 | blue | ball | 1.2 |
Наконец, если необходимо получить одно значение из объекта, сперва нужно указать название колонки, а потом — индекс или метку строки.
>>> frame['object'][3] 'paper'
Присваивание и замена значений
Разобравшись с логикой получения доступа к разным элементам Dataframe , можно следовать ей же для добавления новых или изменения уже существующих значений.
Например, в структуре Dataframe массив индексов определен атрибутом index , а строка с названиями колонок — columns . Можно присвоить метку с помощью атрибута name для этих двух подструктур, чтобы идентифицировать их.
>>> frame.index.name = 'id' >>> frame.columns.name = 'item' >>> frame
item | color | object | price |
---|---|---|---|
id | |||
0 | blue | ball | 1.2 |
1 | green | pen | 1.0 |
2 | yellow | pencil | 0.6 |
3 | red | paper | 0.9 |
4 | white | mug | 1.7 |
Одна из главных особенностей структур данных pandas — их гибкость. Можно вмешаться на любом уровне для изменения внутренней структуры данных. Например, добавление новой колонки — крайне распространенная операция.
Ее можно выполнить, присвоив значение экземпляру Dataframe и определив новое имя колонки.
>>> frame['new'] = 12 >>> frame
item | color | object | price | new |
---|---|---|---|---|
id | ||||
0 | blue | ball | 1.2 | 12 |
1 | green | pen | 1.0 | 12 |
2 | yellow | pencil | 0.6 | 12 |
3 | red | paper | 0.9 | 12 |
4 | white | mug | 1.7 | 12 |
Здесь видно, что появилась новая колонка new со значениями 12 для каждого элемента.
Для обновления значений можно использовать массив.
frame['new'] = [3.0, 1.3, 2.2, 0.8, 1.1] frame
item | color | object | price | new |
---|---|---|---|---|
id | ||||
0 | blue | ball | 1.2 | 3.0 |
1 | green | pen | 1.0 | 1.3 |
2 | yellow | pencil | 0.6 | 2.2 |
3 | red | paper | 0.9 | 0.8 |
4 | white | mug | 1.7 | 1.1 |
Тот же подход используется для обновления целой колонки. Например, можно применить функцию np.arrange() для обновления значений колонки с помощью заранее заданной последовательности.
Колонки Dataframe также могут быть созданы с помощью присваивания объекта Series одной из них, например, определив объект Series , содержащий набор увеличивающихся значений с помощью np.arrange() .
>>> ser = pd.Series(np.arange(5)) >>> ser 0 0 1 1 2 2 3 3 4 4 dtype: int32
frame['new'] = ser frame
item | color | object | price | new |
---|---|---|---|---|
id | ||||
0 | blue | ball | 1.2 | 0 |
1 | green | pen | 1.0 | 1 |
2 | yellow | pencil | 0.6 | 2 |
3 | red | paper | 0.9 | 3 |
4 | white | mug | 1.7 | 4 |
Наконец, для изменения одного значения нужно лишь выбрать элемент и присвоить ему новое значение.
>>> frame['price'][2] = 3.3
Вхождение значений
Функция isin() используется с объектами Series для определения вхождения значений в колонку. Она же подходит и для объектов Dataframe .
>>> frame.isin([1.0,'pen'])
item | color | object | price | new |
---|---|---|---|---|
id | ||||
0 | False | False | False | False |
1 | False | True | True | True |
2 | False | False | False | False |
3 | False | False | False | False |
4 | False | False | False | False |
Возвращается Dataframe с булевыми значениями, где True указывает на те значения, где членство подтверждено. Если передать это значение в виде условия, тогда вернется Dataframe , где будут только значения, удовлетворяющие условию.
>>> frame[frame.isin([1.0,'pen'])]
item | color | object | price | new |
---|---|---|---|---|
id | ||||
0 | NaN | NaN | NaN | NaN |
1 | NaN | pen | 1.0 | 1.0 |
2 | NaN | NaN | NaN | NaN |
3 | NaN | NaN | NaN | NaN |
4 | NaN | NaN | NaN | NaN |
Удаление колонки
Для удаления целой колонки и всего ее содержимого используется команда del .
>>> del frame['new'] >>> frame
item | color | object | price |
---|---|---|---|
id | |||
0 | blue | ball | 1.2 |
1 | green | pen | 1.0 |
2 | yellow | pencil | 3.3 |
3 | red | paper | 0.9 |
4 | white | mug | 1.7 |
Фильтрация
Даже для Dataframe можно применять фильтры, используя определенные условия. Например, вам нужно получить все значения меньше определенного числа (допустим, 1,2).
>>> frame[frame 1.2]
item | color | object | price |
---|---|---|---|
id | |||
0 | blue | ball | NaN |
1 | green | pen | 1.0 |
2 | yellow | pencil | NaN |
3 | red | paper | 0.9 |
4 | white | mug | NaN |
Результатом будет Dataframe со значениями меньше 1,2 на своих местах. На месте остальных будет NaN .
Dataframe из вложенного словаря
В Python часто используется вложенный dict :
>>> nestdict = 'red': 2012: 22, 2013: 33>, ... 'white': 2011: 13, 2012: 22, 2013: 16>, ... 'blue': 2011: 17, 2012: 27, 2013: 18>>
Эта структура данных, будучи переданной в качестве аргумента в DataFrame() , интерпретируется pandas так, что внешние ключи становятся названиями колонок, а внутренние — метками индексов.
При интерпретации вложенный структуры возможно такое, что не все поля будут совпадать. pandas компенсирует это несоответствие, добавляя NaN на место недостающих значений.
>>> nestdict = 'red': 2012: 22, 2013: 33>, ... 'white': 2011: 13, 2012: 22, 2013: 16>, ... 'blue': 2011: 17, 2012: 27, 2013: 18>> >>> frame2 = pd.DataFrame(nestdict) >>> frame2
blue | red | white | |
---|---|---|---|
2011 | 17 | NaN | 13 |
2012 | 27 | 22.0 | 22 |
2013 | 18 | 33.0 | 16 |
Транспонирование Dataframe
При работе с табличным структурами данных иногда появляется необходимость выполнить операцию перестановки (сделать так, чтобы колонки стали рядами и наоборот). pandas позволяет добиться этого очень просто. Достаточно добавить атрибут T .
>>> frame2.T
2011 | 2012 | 2013 | |
---|---|---|---|
blue | 17.0 | 27.0 | 18.0 |
red | NaN | 22.0 | 33.0 |
white | 13.0 | 22.0 | 16.0 |
Объекты Index
Зная, что такое Series и Dataframes , и понимая как они устроены, проще разобраться со всеми их достоинствами. Главная особенность этих структур — наличие объекта Index , который в них интегрирован.
Объекты Index являются метками осей и содержат другие метаданные. Вы уже знаете, как массив с метками превращается в объект Index , и что для него нужно определить параметр index в конструкторе.
>>> ser = pd.Series([5,0,3,8,4], index=['red','blue','yellow','white','green']) >>> ser.index Index(['red', 'blue', 'yellow', 'white', 'green'], dtype='object')
В отличие от других элементов в структурах данных pandas ( Series и Dataframe ) объекты index — неизменяемые. Это обеспечивает безопасность, когда нужно передавать данные между разными структурами.
У каждого объекта Index есть методы и свойства, которые нужны, чтобы узнавать значения.
Методы Index
Есть методы для получения информации об индексах из структуры данных. Например, idmin() и idmax() — структуры, возвращающие индексы с самым маленьким и большим значениями.
>>> ser.idxmin() 'blue' >>> ser.idxmax() 'white'
Индекс с повторяющимися метками
Пока что были только те случаи, когда у индексов одной структуры лишь одна, уникальная метка. Для большинства функций это обязательное условие, но не для структур данных pandas.
Определим, например, Series с повторяющимися метками.
>>> serd = pd.Series(range(6), index=['white','white','blue','green', 'green','yellow']) >>> serd white 0 white 1 blue 2 green 3 green 4 yellow 5 dtype: int64
Если метке соответствует несколько значений, то она вернет не один элемент, а объект Series .
>>> serd['white'] white 0 white 1 dtype: int64
То же применимо и к Dataframe . При повторяющихся индексах он возвращает Dataframe .
В случае с маленькими структурами легко определять любые повторяющиеся индексы, но если структура большая, то растет и сложность этой операции. Для этого в pandas у объектов Index есть атрибут is_unique . Он сообщает, есть ли индексы с повторяющимися метками в структуре ( Series или Dataframe ).
>>> serd.index.is_unique False >>> frame.index.is_unique True
Операции между структурами данных
Теперь когда вы знакомы со структурами данных, Series и Dataframe , а также базовыми операциями для работы с ними, стоит рассмотреть операции, включающие две или более структур.
Гибкие арифметические методы
Уже рассмотренные операции можно выполнять с помощью гибких арифметических методов:
Для их вызова нужно использовать другую спецификацию. Например, вместо того чтобы выполнять операцию для двух объектов Dataframe по примеру frame1 + frame2 , потребуется следующий формат:
>>> frame1.add(frame2)
ball | mug | paper | pen | pencil | |
---|---|---|---|---|---|
blue | 6.0 | NaN | NaN | 6.0 | NaN |
green | NaN | NaN | NaN | NaN | NaN |
red | NaN | NaN | NaN | NaN | NaN |
white | 20.0 | NaN | NaN | 20.0 | NaN |
yellow | 19.0 | NaN | NaN | 19.0 | NaN |
Результат такой же, как при использовании оператора сложения + . Также стоит обратить внимание, что если названия индексов и колонок сильно отличаются, то результатом станет новый объект Dataframe , состоящий только из значений NaN .
Операции между Dataframe и Series
Pandas позволяет выполнять переносы между разными структурами, например, между Dataframe и Series . Определить две структуры можно следующим образом.
>>> frame = pd.DataFrame(np.arange(16).reshape((4,4)), ... index=['red', 'blue', 'yellow', 'white'], ... columns=['ball','pen','pencil','paper']) >>> frame
ball | pen | pencil | paper | |
---|---|---|---|---|
red | 0 | 1 | 2 | 3 |
blue | 4 | 5 | 6 | 7 |
yellow | 8 | 9 | 10 | 11 |
white | 12 | 13 | 14 | 15 |
>>> ser = pd.Series(np.arange(4), index=['ball','pen','pencil','paper']) >>> ser ball 0 pen 1 pencil 2 paper 3 dtype: int32
Они были специально созданы так, чтобы индексы в Series совпадали с названиями колонок в Dataframe . В таком случае можно выполнить прямую операцию.
>>> frame - ser
ball | pen | pencil | paper | |
---|---|---|---|---|
red | 0 | 0 | 0 | 0 |
blue | 4 | 4 | 4 | 4 |
yellow | 8 | 8 | 8 | 8 |
white | 12 | 12 | 12 | 12 |
По результату видно, что элементы Series были вычтены из соответствующих тому же индексу в колонках значений Dataframe .
Если индекс не представлен ни в одной из структур, то появится новая колонка с этим индексом и значениями NaN .
>>> ser['mug'] = 9 >>> ser ball 0 pen 1 pencil 2 paper 3 mug 9 dtype: int64
>>> frame - ser
ball | mug | paper | pen | pencil | |
---|---|---|---|---|---|
red | 0 | NaN | 0 | 0 | 0 |
blue | 4 | NaN | 4 | 4 | 4 |
yellow | 8 | NaN | 8 | 8 | 8 |
white | 12 | NaN | 12 | 12 | 12 |
Pandas основные объекты. Series
Series — это одномерный помеченный массив, способный хранить данные любого типа.
Параметр | Описание |
data | массив данные принимают различные формы, такие как ndarray, list, constants |
index | значения индекса должны быть уникальными и иметь хешируемую длину и соответствовать данным. |
dtype | dtype для типа данных. Если None, то определяется автоматически |
copy | копирование данных, по-умолчание false |
import pandas as pd
Series может быть создана с помощью следующего конструктора
data = pd.Series([0.25, 0.5, 0.75, 1.0]) print(data)
0 0.25 1 0.50 2 0.75 3 1.00 dtype: float64
Как мы видим из выходных данных, Series оборачивает как последовательность значений, так и последовательность индексов, к которым мы можем обращаться с помощью values и атрибутов index.
При вызове values выводится все значение.
print(data.values)
array([ 0.25, 0.5 , 0.75, 1. ])
А при index возрождается объект RangeIndex.
print(data.index)
RangeIndex(start=0, stop=4, step=1)
Доступ к данным можно получить с помощью ассоциированного индекса через знакомую запись в квадратных скобках Python:
data[1]
data[1:3]
1 0.50 2 0.75 dtype: float64
А также доступ осуществляется с использованием .loc или .iloc.
data = pd.Series(['Понедельник', 'Вторник', 'Cреда', 'Четверг'], index = ['Первый', "Второй", "Третий", "Четвёртый"])
.loc в него принимают указатель индекс или массив указателей. Например:
data.loc["Первый"] data.loc[["Первый", "Третий"]]
А в .iloc принимает индекс или массив индексов
data.iloc[0] data.iloc[[0, 2]]
Если в .loc передать название индекса, а в .iloc номер индекса, которого нет в данных, то будет вызвана ошибка.
Основы работы с Pandas: Series и DataFrames
Одним из наиболее популярных инструментов для системного анализа данных является Pandas. Давайте рассмотрим, какими особенностями обладает данная библиотека, для чего и как используется. Предложенная информацию будет полезна не только новичкам, но и опытным специалистам.
Описание
Pandas – программная библиотека, написанная на Python. Она используется для обработки и анализа данных. Работа здесь строится поверх library NumPy.
Если говорить простыми словами, Pandas – это как Excel, но мощнее. Здесь программист сможет работать с данными, объемом в тысячи и даже миллионы строк. Pandas предоставляет высокопроизводительные структуры информации, а также инструменты для их анализа.
Ключевые функции
Pandas широко используется в разработке. Она обеспечивает простоту в рамках среды Python. Используется для:
- сбора и очистки данных;
- задач, связанных с анализом информации;
- моделирования данных без переключения на специфичные для стартовой обработки языки (пример – Octave или R).
Библиотека предназначается для очистки, а также первичной оценки данных по общим показателям. Пример – среднее значение, квантили и так далее.
Pandas – это не статистический пакет, но его наборы информации применяются в виде входных в большинстве модулей анализа данных, а также при машинном обучении.
Для чего нужен проект
Pandas – это ключевая библиотека Питона, необходимая для работы с электронными материалами. Активно используется специалистами по BigDatas. Часто применяется для следующих задач:
- Аналитика. Инструмент позволяет подготовить datas к дальнейшему использованию. Он удаляет или заполняет пропуски, проводит сортировку или вносит необходимые изменения. Обычно большую часть соответствующих процессов удается автоматизировать через изучаемый проект.
- Data Science. Используется для подготовки и первичного анализа имеющихся сведений. Это необходимо для машинного/глубокого обучения.
- Статистика. В изучаемом проекте поддерживаются ключевые статистические методы. Они позволяют работать с информацией в электронном виде максимально эффективно и быстро. Пример – расчет средних значений.
Инструмент используется не только для обработки информации, но и для ее визуализации. Легко осваивается как опытными разработчиками, так и новичками.
Историческая справка
Рассматриваемый инструмент начал разрабатываться Уэсом Маккини, работающем в AQR Capital Management, в 2008 году. Он смог убедить работодателя перед увольнением разрешить опубликовать исходный код библиотеки. Так она получила открытость и свободную лицензию.
Позже, в 2012 году, к поддержке и совершенствованию продукта присоединился еще один сотрудник AQR – Чан Шэ. Он стал вторым главным разработчиком проекта. Примерно в этот момент Пандас стала набирать популярность в Python. Теперь соответствующий инструмент активно совершенствуется и дорабатывается свободными разработчиками.
Ключевые возможности
Рассматриваемый продукт для Питона обладает мощным функционалом. Он поддерживает следующие возможности:
- объекты data frame для управления индексированными массивами двумерной информации;
- встроенные средства совмещения данных, а также способы обработки сопутствующих сведений;
- инструменты, необходимые для обмена электронными материалами между структурами памяти, а также всевозможными файлами и документами;
- срезы по значениям индексов;
- расширенные возможности при индексировании;
- наличие выборки из больших объемов наборов информации;
- вставка, а также удаление столбцов в массиве;
- встроенные средства совмещения информации;
- обработка отсутствующих сведений;
- слияние и объединение имеющихся информационных наборов;
- иерархическое индексирование, при помощи которой удается обрабатывать материалы высокой размерности в структурах с меньшей размерностью;
- группировка, позволяющая выполнять трехэтапные операции типа «разделение, изменение и объединение» одновременно.
Проект поддерживает временные ряды. Он позволяет формировать временные периоды, изменять интервалы и так далее. Изначально создавался для обеспечения высокой производительности. Наиболее важные его части сформированы на C и Cython.
Начало работы
Pandas – функциональный и удобный проект для обработки данных. Далее предстоит разобраться с основами работы с ним. Для машинного обучения часто используются специальные библиотеки – Google Colab и Jupyter Notebook. Такие названия получили специализированные IDE. Они дают возможность работать с данными итеративно и пошагово. При их применении не требуется писать полноценное программное обеспечение.
Рекомендуется сначала установить IDE. В них Pandas встроен по умолчанию – ничего и никуда инициализировать не придется. Остается лишь произвести импорт в исходный код.
Если не использовать специализированные среды, разработчику потребуется Python выше версии 2.7. Импортирование Пандас происходит при помощи такой команды:
или , где pd – это официальное сокращение Pandas.
При использовании PIP необходимо воспользоваться следующей командой:
Для импорта PD и NumPy в Python-скрипт потребуется добавить такой блок кода:
Связано это с тем, что PD зависит от NumPy. Соответствующая зависимость тоже должна быть импортирована в исходный код приложения. Теперь все готово к полноценному применению модуля при разработке программных продуктов разной сложности.
Структуры данных
Изучаемый модуль поддерживает несколько информационных структур:
- Series. Выражается одномерным массивом неизменного размера. Напоминает структуру с однородными данными.
- DataFrames. Двумерная табличная структуру. Поддерживает изменение размера. Столбцы в ней будут неоднородно типизированными.
- Panel. Трехмерный массив, который может меняться в размерах.
Других вариантов у PD нет. Далее первые две структурные единицы будут изучены более подробно. Они используются в программных кодах чаще всего.
Класс Series
Series – объект, который напоминает одномерный массив. Может включать в себя любые типы данных. Часто представлен в виде столбца таблицы с последовательностями тех или иных значений. Каждый из них будет наделен индексом – номером строки.
При обработке соответствующего кода на экране появится такая запись:
Series будет отображаться в виде таблицы с индексами компонентов. Соответствующая информация выводится в первом столбце. Второй отводится непосредственно под заданные значения.
Data Frame
DataFrame – это таблица с разными типами столбцов. Представляет собой двумерную информационную структуру. Является основным типом информации в Pandas. Вокруг DataFrame строится вся дальнейшая работа.
Соответствующий объект может быть представлен обычной таблицей (подобной той, что встречается в Excel), с любым количеством не только строк, но и столбцов. Внутри ее ячеек содержатся самые разные сведения:
- числовые;
- булевы;
- строковые и так далее.
DataFrame имеет индексы не только столбцов, но и строк. За счет подобной особенности удается сортировать и фильтровать сведения и находить нужные значения быстро и максимально комфортно.
В DataFrame поддерживается жесткое кодирование, а также импорт:
- CSV;
- TSV;
- Excel-документов;
- SQL-таблиц.
Для создания соответствующего компонента допускается использование команды:
- data – это создание объекта из входных сведений (NumPy, series, dict и им подобные);
- index – строковые метки;
- columns – создание подписей столбцов;
- dtype – ссылка на тип сведений, содержащихся в каждом столбце (этот параметр не является обязательным);
- copy – копирование сведений, если они предусмотрены изначально.
Создание DataFrame может производиться различными способами. Пример – формирование объекта из словаря или их списков, кортежей, файла Excel.
Вот пример кода, использующего список словарей для создания DataFrame:
При обработке предложенного фрагмента система выведен на терминал/экран устройства следующую информацию:
Работает код достаточно просто: сначала создается словарь, а затем в него передается в качестве аргумента метод DataFrame(). После получения тех или иных значений система выводит объект на печать в терминале.
Индекс здесь будет отображаться в самом первом левом столбце. Он имеет метки строк. Заголовки и электронные материалы – это сама таблица. При помощи настройки индексных параметров удается создавать индексированные DataFrames.
Импорт CSV
При создании DataFrame можно воспользоваться импортом файла CSV. Так называется текстовый документ. В нем запись материалов и значений ведется в каждой строке, разделяясь символом запятой.
Pandas поддерживает метод read_csv. С его помощью удается считывать содержимое CSV. Соответствующая команда поддерживает несколько параметров управления импортом:
- Sep. Он позволяет явно указывать разделители, используемые при выгрузке материалов. По умолчанию это символ запятой. Данный параметр является полезным при нестандартных разделителях в исходном документе. Пример – когда там применяются точки с запятыми или табуляция.
- Dtype. При помощи этой характеристики удается явно указывать тип, используемый в столбцах. Применяется, когда автоматически определяемый формат оказывается неверным. Пример – если дата импортируется в качестве строковой переменной.
А вот фрагмент кода, позволяющий импортировать сведения о скорости мобильного и стационарного интернета в разных странах. Здесь необходимо скачать исходный документ. После этого останется указать метод:
Чтобы увидеть DataFrame, останется вывести его на печать:
При работе в Jupiter Notebook и Google Collab для вывода DataFrame, а также Series, необходимо использовать команду print. Без нее модуль тоже сможет показать интересующие сведения. При написании print(df) будет потеряна табличная верстка.
В верхней части – названия столбцов, а слева указываются индексы. В нижней части выводится детализация о количестве столбцов и строк.
Полностью выводить табличку не обязательно. Для первого знакомства достаточно первых или последних пяти строчек. Чтобы воспользоваться соответствующими операциями, рекомендуется использование df.head() или df.tail() соответственно. В скобках указывается, сколько строчек выводить на экран. Этот параметр в Pandas по умолчанию равен 5.
Здесь можно увидеть больше информации об изученном модуле. А лучше программировать с его применением в Python помогут специализированные дистанционные компьютерные курсы.
Интересуют курсы по системному анализу и не только? Огромный выбор обучающих онлайн-программ по востребованным IT-направлениям есть в Otus !