Во втором уроке мы познакомимся со структурами данных pandas – это Series и DataFrame. Основное внимание будет уделено вопросам создания и получения доступа к элементам данных структур, а также общим понятиям, которые позволят более интуитивно работать с ними в будущем.
Введение
Библиотека pandas предоставляет две структуры: Series и DataFrame для быстрой и удобной работы с данными (на самом деле их три, есть еще одна структура – Panel, но в данный момент она находится в статусе deprecated и в будущем будет исключена из состава библиотеки pandas). Series – это маркированная одномерная структура данных, ее можно представить, как таблицу с одной строкой. С Series можно работать как с обычным массивом (обращаться по номеру индекса), и как с ассоциированным массивом, когда можно использовать ключ для доступа к элементам данных. DataFrame – это двумерная маркированная структура. Идейно она очень похожа на обычную таблицу, что выражается в способе ее создания и работе с ее элементами. Panel – про который было сказано, что он вскоре будет исключен из pandas, представляет собой трехмерную структуру данных. О Panel мы больше говорить не будем. В рамках этой части мы остановимся на вопросах создания и получения доступа к элементам данных структур Series и DataFrame.
Структура данных Series
Для того, чтобы начать работать со структурами данных из pandas требуется предварительно импортировать необходимые модули. Убедитесь, что нужные модули установлены на вашем компьютере, о том, как это сделать, можно прочитать в первой части данного курса. Также будем считать, что вы знакомы с языком Python. Если нет, то специально для вас мы подготовили он-лайн курс и книгу.
Помимо самого pandas нам понадобится библиотека numpy. Наши эксперименты будем проводить с использованием пакета Anaconda, в качестве среды разработки советуем взять Spyder, который входит в базовую поставку Anaconda. Для того, чтобы запустить Spyder, перейдите в каталог Scripts, который находится в папке с установленной Anaconda и запустите spyder.exe. Для нас он в первую очередь имеет ценность в том, что в нем есть редактор исходного кода, на случай, если нам понадобится написать довольно большую программу, и интерпретатор для быстрых экспериментов. Если строки кода будут содержать префикс в виде цифры в квадратных скобках, то это означает, что данные команды мы вводим в интерпретаторе, в ином случае, это будет означать, что код написан в редакторе.
Пора переходить к практике!
Импортируем нужные нам библиотеки.
In [1]: import numpy as np In [2]: import pandas as pd
Создать структуру Series можно на базе различных типов данных:
- словари Python;
- списки Python;
- массивы из numpy: ndarray;
- скалярные величины.
Конструктор класса Series выглядит следующим образом:
pandas.Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False)
data – массив, словарь или скалярное значение, на базе которого будет построен Series;
index – список меток, который будет использоваться для доступа к элементам Series. Длина списка должна быть равна длине data;
dtype – объект numpy.dtype, определяющий тип данных;
copy – создает копию массива данных, если параметр равен True в ином случае ничего не делает.
В большинстве случаев, при создании Series, используют только первые два параметра. Рассмотрим различные варианты как это можно сделать.
Создание Series из списка Python
Самый простой способ создать Series – это передать в качестве единственного параметра в конструктор класса список Python.
In [3]: s1 = pd.Series([1, 2, 3, 4, 5]) In [4]: print(s1) 0 1 1 2 2 3 3 4 4 5 dtype: int64
В данном примере была создана структура Series на базе списка из языка Python. Для доступа к элементам Series, в данном случае, можно использовать только положительные целые числа – левый столбец чисел, начинающийся с нуля – это как раз и есть индексы элементов структуры, которые представлены в правом столбце.
Можно попробовать использоваться больше возможностей из тех, что предлагает pandas, для этого передадим в качестве второго элемента список строк (в нашем случае – это отдельные символы). Такой шаг позволит нам обращаться к элементам структуры Series не только по численному индексу, но и по метке, что сделает работу с таким объектом, похожей на работу со словарем.
In [5]: s2 = pd.Series([1, 2, 3, 4, 5], ['a', 'b', 'c', 'd', 'e']) In [6]: print(s2) a 1 b 2 c 3 d 4 e 5 dtype: int64
Обратите внимание на левый столбец, в нем содержатся метки, которые мы передали в качестве index параметра при создании структуры. Правый столбец – это по-прежнему элементы нашей структуры.
Создание Series из ndarray массива из numpy
Создадим простой массив из пяти чисел, аналогичный списку из предыдущего раздела. Библиотеки pandas и numpy должны быть предварительно импортированы.
In [3]: ndarr = np.array([1, 2, 3, 4, 5]) In [4]: type(ndarr) Out[4]: numpy.ndarray
Теперь создадим Series с буквенными метками.
In [5]: s3 = pd.Series(ndarr, ['a', 'b', 'c', 'd', 'e']) In [6]: print(s3) a 1 b 2 c 3 d 4 e 5 dtype: int32
Создание Series из словаря (dict)
Еще один способ создать структуру Series – это использовать словарь для одновременного задания меток и значений.
In [7]: d = {'a':1, 'b':2, 'c':3} In [8]: s4 = pd.Series(d) In [9]: print(s4) a 1 b 2 c 3 dtype: int64
Ключи (keys) из словаря d станут метками структуры s4, а значения (values) словаря – значениями в структуре.
Создание Series с использованием константы
Рассмотрим еще один способ создания структуры. На этот раз значения в ячейках структуры будут одинаковыми.
In [10]: a = 7 In [11]: s5 = pd.Series(a, ['a', 'b', 'c']) In [12]: print(s5) a 7 b 7 c 7 dtype: int64
В созданной структуре Series имеется три элемента с одинаковым содержанием.
Работа с элементами Series
В будущем будет написан отдельный урок, посвященный индексации и работе с элементами Series и DataFrame, сейчас рассмотрим основные подходы.
К элементам Series можно обращаться по численному индексу, при таком подходе работа со структурой не отличается от работы со списками в Python.
In [13]: s6 = pd.Series([1, 2, 3, 4, 5], ['a', 'b', 'c', 'd', 'e']) In [14]: s6[2] Out[14]: 3
Можно использовать метку, тогда работа с Series будет похожа на работу со словарем (dict) в Python.
In [15]: s6['d'] Out[15]: 4
Доступно получение slice’ов.
In [16]: s6[:2] Out[16]: a 1 b 2 dtype: int64
В поле для индекса можно поместить условное выражение.
In [17]: s6[s6 <= 3] Out[17]: a 1 b 2 c 3 dtype: int64
Со структурами Series можно работать как с векторами: складывать, умножать вектор на число и т.п.
In [18]: s7 = pd.Series([10, 20, 30, 40, 50], ['a', 'b', 'c', 'd', 'e']) In [19]: s6 + s7 Out[19]: a 11 b 22 c 33 d 44 e 55 dtype: int64 In [20]: s6 * 3 Out[20]: a 3 b 6 c 9 d 12 e 15 dtype: int64
Структура данных DataFrame
Если Series представляет собой одномерную структуру, которую для себя можно представить как таблицу с одной строкой, то DataFrame – это уже двумерная структура – полноценная таблица с множеством строк и столбцов.
Перед работой с DataFrame не забудьте импортировать библиотеку pandas.
Конструктор класса DataFrame выглядит так:
class pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)
data – массив ndarray, словарь (dict) или другой DataFrame;
index – список меток для записей (имена строк таблицы);
columns – список меток для полей (имена столбцов таблицы);
dtype – объект numpy.dtype, определяющий тип данных;
copy – создает копию массива данных, если параметр равен True в ином случае ничего не делает.
Структуру DataFrame можно создать на базе:
- словаря (dict) в качестве элементов которого должны выступать: одномерные ndarray, списки, другие словари, структуры Series;
- двумерные ndarray;
- структуры Series;
- структурированные ndarray;
- другие DataFrame.
Рассмотрим на практике различные подходы к созданию DataFrame’ов.
Создание DataFrame из словаря
В данном случае будет использоваться одномерный словарь, элементами которого будут списки, структуры Series и т.д.
Начнем с Series.
In [3]: d = {"price":pd.Series([1, 2, 3], index=['v1', 'v2', 'v3']), ...: "count": pd.Series([10, 12, 7], index=['v1', 'v2', 'v3'])} In [4]: df1 = pd.DataFrame(d) In [5]: print(df1) count price v1 10 1 v2 12 2 v3 7 3 In [6]: print(df1.index) Index(['v1', 'v2', 'v3'], dtype='object') In [7]: print(df1.columns) Index(['count', 'price'], dtype='object')
Теперь построим аналогичный словарь, но на элементах ndarray.
In [8]: d2 = {"price":np.array([1, 2, 3]), ...: "count": np.array([10, 12, 7])} In [9]: df2 = pd.DataFrame(d2, index=['v1', 'v2', 'v3']) In [10]: print(df2) count price v1 10 1 v2 12 2 v3 7 3 In [11]: print(df2.index) Index(['v1', 'v2', 'v3'], dtype='object') In [12]: print(df2.columns) Index(['count', 'price'], dtype='object')
Как видно – результат аналогичен предыдущему. Вместо ndarray можно использовать обычный список из Python.
Создание DataFrame из списка словарей
До это мы создавали DataFrame из словаря, элементами которого были структуры Series, списки и массивы, сейчас мы создадим DataFrame из списка, элементами которого являются словари.
In [13]: d3 = [{"price": 3, "count":8}, {"price": 4, "count": 11}] In [14]: df3 = pd.DataFrame(d3) In [15]: print(df3) count price 0 8 3 1 11 4 In [16]: print(df3.info()) <class 'pandas.core.frame.DataFrame'> RangeIndex: 2 entries, 0 to 1 Data columns (total 2 columns): count 2 non-null int64 price 2 non-null int64 dtypes: int64(2) memory usage: 112.0 bytes None
Создание DataFrame из двумерного массива
Создать DataFrame можно также и из двумерного массива, в нашем примере это будет ndarray из библиотеки numpy.
In [17]: nda1 = np.array([[1, 2, 3], [10, 20, 30]]) In [18]: df4 = pd.DataFrame(nda1) In [19]: print(df4) 0 1 2 0 1 2 3 1 10 20 30
Работа с элементами DataFrame
Работа с элементами DataFrame – доступ к элементам данной структуры – тема достаточно обширная и она будет освещена в одном из ближайших уроков. Сейчас мы рассмотрим наиболее часто используемые способы работы с элементами DataFrame.
Основные подходы представлены в таблице ниже.
Операция | Синтаксис | Возвращаемый результат |
Выбор столбца | df[col] | Series |
Выбор строки по метке | df.loc[label] | Series |
Выбор строки по индексу | df.iloc[loc] | Series |
Слайс по строкам | df[0:4] | DataFrame |
Выбор строк, отвечающих условию | df[bool_vec] | DataFrame |
Теперь посмотрим, как использовать данные операций на практике.
Для начала создадим DataFrame.
In [3]: d = {"price":np.array([1, 2, 3]), ...: "count": np.array([10, 20, 30])} In [4]: df = pd.DataFrame(d, index=['a', 'b', 'c']) In [5]: print(df) count price a 10 1 b 20 2 c 30 3
Операция: выбор столбца.
In [6]: df['count'] Out[6]: a 10 b 20 c 30 Name: count, dtype: int32
Операция: выбор строки по метке.
In [7]: df.loc['a'] Out[7]: count 10 price 1 Name: a, dtype: int32
Операция: выбор строки по индексу.
In [8]: df.iloc[1] Out[8]: count 20 price 2 Name: b, dtype: int32
Операция: slice по строкам.
In [9]: df[0:2] Out[9]: count price a 10 1 b 20 2
Операция: выбор строк, отвечающих условию.
In [10]: df[df['count'] >= 20] Out[10]: count price b 20 2 c 30 3
P.S.
Все уроки по библиотеке Pandas собраны в книге “Pandas. Работа с данными”.
<<<Урок 3. Доступ к данным в структурах pandas Урок 1. Введение в pandas и его установка>>>
Опечатка: случае[т]
В большинстве случает, при создании Series
P.S. Спасибо за статью!
Спасибо! Поправили))
> Конструктор класса Series выглядит следующим образом:
> … fastpath=False
Про этот параметр ничего не сказали.
Спасибо! Добавим!
И слово “slice”, которое вы как только не склоняете здесь и далее в книге, переводится как “срез”. Это вполне себе русское и подходящее по смыслу слово.
Как мне кажется, ‘slice’ стало уже сленговым словом, и его вполне можно употреблять. Но слово ‘срез’ звучит тоже не плохо))) В данном случае выбор был сделан в пользу первого.