Изучаем pandas.Структуры данных Series и DataFrame

В этом уроке мы познакомимся со структурами данных 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.
Основные подходы представлены в таблице ниже.
Теперь посмотрим, как использовать данные операций на практике.
Для начала создадим 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
