pandas
Чтобы начать работать с pandas
, рассмотрим две основные структуры:
Series
и DataFrame
. Они не являются универсальными решениями любых
задач, однако эти структуры предоставляют прочный легкий в
использовании фундамент для большинства приложений.
Series
Series
(ряд) — объект, типа одномерного массива, содержащий
последовательность значений (типов, аналогичных типам NumPy) и
связанный с ним массив меток данных,
называемых индексами. Создадим простейший объект типа Series
только из массива данных:
In [2]: obj = pd.Series([4, 7, -5, 3])
In [3]: obj
Out[3]:
0 4
1 7
2 -5
3 3
dtype: int64
Строковое представление объекта Series
в интерактивном режиме
отображает индексы слева, а данные справа. Так как мы не определили
индексы, то по умолчанию индексы содержат целые числа от 0
до N-1
(где N
— длина массива данных). Можно получить представление в виде
массива и индексы ряда с помощью атрибутов values
и index
:
In [4]: obj.values
Out[4]: array([ 4, 7, -5, 3])
In [5]: obj.index # как range(4)
Out[5]: RangeIndex(start=0, stop=4, step=1)
Часто желательно создать ряд с индексами, идентифицирующими каждую точку данный с меткой:
In [6]: obj2 = pd.Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c'])
In [7]: obj2
Out[7]:
d 4
b 7
a -5
c 3
dtype: int64
In [8]: obj2.index
Out[8]: Index(['d', 'b', 'a', 'c'], dtype='object')
В отличие от массивов NumPy, можно использовать метки при индексации при выборе отдельных значений или набора значений:
In [9]: obj2['a']
Out[9]: -5
In [10]: obj2['d'] = 6
In [11]: obj2[['c', 'a', 'd']]
Out[11]:
c 3
a -5
d 6
dtype: int64
Использование функций NumPy или операций подобных NumPy, таких как фильтрация с помощью булевых массивов, умножение на скаляр или вычисление математических функций, сохраняет значения индексов:
In [12]: obj2[obj2 > 0]
Out[12]:
d 6
b 7
c 3
dtype: int64
In [13]: obj2 * 2
Out[13]:
d 12
b 14
a -10
c 6
dtype: int64
In [14]: import numpy as np
In [15]: np.exp(obj2)
Out[15]:
d 403.428793
b 1096.633158
a 0.006738
c 20.085537
dtype: float64
Ряды можно рассматривать как словари фиксированной длины:
In [16]: 'b' in obj2
Out[16]: True
In [17]: 'e' in obj2
Out[17]: False
Если имеются данные, содержащиеся в словаре, можно создать ряд из него:
In [18]: sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}
In [19]: obj3 = pd.Series(sdata)
In [20]: obj3
Out[20]:
Ohio 35000
Texas 71000
Oregon 16000
Utah 5000
dtype: int64
Если передается только словарь, то индексами ряда будут ключи словаря в том порядке, в котором были при создании словаря. Можно изменить порядок индекса передавая ключи словаря в порядке, который нужен:
In [21]: states = ['California', 'Ohio', 'Oregon', 'Texas']
In [22]: obj4 = pd.Series(sdata, index=states)
In [23]: obj4
Out[23]:
California NaN
Ohio 35000.0
Oregon 16000.0
Texas 71000.0
dtype: float64
Здесь три значения, найденные в sdata
, были размещены в
соответствующих местах, но так как не было найдено значение для
'California'
, оно отображается как NaN
(не число), которое в
pandas
используется для обозначение пропущенных значений или
значений «NA» (not available). Поскольку 'Юта'
не была включена в states
,
этот элемент исключается из результирующего объекта. Функции isnull
и notnull
в pandas
используются для обнаружения отсутствующих
данных:
In [24]: pd.isnull(obj4)
Out[24]:
California True
Ohio False
Oregon False
Texas False
dtype: bool
In [25]: pd.notnull(obj4)
Out[25]:
California False
Ohio True
Oregon True
Texas True
dtype: bool
Класс Series
также имеет эти методы:
In [26]: obj4.isnull()
Out[26]:
California True
Ohio False
Oregon False
Texas False
dtype: bool
Полезное свойство Series
заключается в том, что она автоматически
происходит выравнивание по индексам в арифметических операциях:
In [27]: obj3
Out[27]:
Ohio 35000
Texas 71000
Oregon 16000
Utah 5000
dtype: int64
In [28]: obj4
Out[28]:
California NaN
Ohio 35000.0
Oregon 16000.0
Texas 71000.0
dtype: float64
In [29]: obj3 + obj4
Out[29]:
California NaN
Ohio 70000.0
Oregon 32000.0
Texas 142000.0
Utah NaN
dtype: float64
Как объекты Series
, так и из индексы имеют атрибут name
:
In [30]: obj4.name = 'population'
In [31]: obj4.index.name = 'state'
In [32]: obj4
Out[32]:
state
California NaN
Ohio 35000.0
Oregon 16000.0
Texas 71000.0
Name: population, dtype: float64
Можно изменять индексы рядов присваиванием:
In [33]: obj
Out[33]:
0 4
1 7
2 -5
3 3
dtype: int64
In [34]: obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan']
In [35]: obj
Out[35]:
Bob 4
Steve 7
Jeff -5
Ryan 3
dtype: int64
DataFrame
DataFrame
представляет собой прямоугольную таблицу данных и содержит
упорядоченную коллекцию столбцов, каждый из которых может иметь
различный тип значения (числовой, строковый, логический и
т.д.). DataFrame
имеет индексы столбцов и строк.
Есть много способов создания объекта DataFrame
, хотя один из
наиболее распространенных — это использование списков, словарей или
массивов NumPy:
In [36]: data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'],
...: 'year': [2000, 2001, 2002, 2001, 2002, 2003],
...: 'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
In [37]: frame = pd.DataFrame(data)
Полученный в результате DataFrame
получит автоматически индексацию
для строк (как в Series
), а индексом столбцов будут ключи словаря:
In [38]: frame
Out[38]:
state year pop
0 Ohio 2000 1.5
1 Ohio 2001 1.7
2 Ohio 2002 3.6
3 Nevada 2001 2.4
4 Nevada 2002 2.9
5 Nevada 2003 3.2
Если используется блокнот Jupyter, объекты DataFrame
будут
отображаться в виде более удобной для просмотра HTML-таблицы.
Для больших DataFrames метод head выбирает только первые пять строк:
In [39]: frame.head()
Out[39]:
state year pop
0 Ohio 2000 1.5
1 Ohio 2001 1.7
2 Ohio 2002 3.6
3 Nevada 2001 2.4
4 Nevada 2002 2.9
Можно задавать другой порядок столбцов:
In [40]: pd.DataFrame(data, columns=['year', 'state', 'pop'])
Out[40]:
year state pop
0 2000 Ohio 1.5
1 2001 Ohio 1.7
2 2002 Ohio 3.6
3 2001 Nevada 2.4
4 2002 Nevada 2.9
5 2003 Nevada 3.2
Если передать столбец, который не содержится в словаре, то в результате будет столбец с отсутствующими значениями:
In [41]: frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'],
...: index=['one', 'two', 'three', 'four',
...: 'five', 'six'])
In [42]: frame2
Out[42]:
year state pop debt
one 2000 Ohio 1.5 NaN
two 2001 Ohio 1.7 NaN
three 2002 Ohio 3.6 NaN
four 2001 Nevada 2.4 NaN
five 2002 Nevada 2.9 NaN
six 2003 Nevada 3.2 NaN
In [43]: frame2.columns
Out[43]: Index(['year', 'state', 'pop', 'debt'], dtype='object')
К столбцу DataFrame
можно получить доступ как к ряду с помощью
нотацией подобной словарю или через атрибут:
In [44]: frame2['state']
Out[44]:
one Ohio
two Ohio
three Ohio
four Nevada
five Nevada
six Nevada
Name: state, dtype: object
In [45]: frame2.year
Out[45]:
one 2000
two 2001
three 2002
four 2001
five 2002
six 2003
Name: year, dtype: int64
IPython предоставлет доступ по атрибуту (например, frame2.year
)
по автодополнению с помощью клавиши
Вариант frame2[column]
работает для любых имен столбцов, в то время
как frame2.column
работает только если имя столбца является
допустимым в Python именем переменной.
К строкам можно получить доступ по позиции или с помощью специального
атрибута loc
:
In [46]: frame2.loc['three']
Out[46]:
year 2002
state Ohio
pop 3.6
debt NaN
Name: three, dtype: object
Можно менять значения столбцов. Например, пустой столбцу debt
можно
присвоить скалярное значение или массив:
In [47]: frame2['debt'] = 16.5
In [48]: frame2
Out[48]:
year state pop debt
one 2000 Ohio 1.5 16.5
two 2001 Ohio 1.7 16.5
three 2002 Ohio 3.6 16.5
four 2001 Nevada 2.4 16.5
five 2002 Nevada 2.9 16.5
six 2003 Nevada 3.2 16.5
In [49]: frame2['debt'] = np.arange(6.)
In [50]: frame2
Out[50]:
year state pop debt
one 2000 Ohio 1.5 0.0
two 2001 Ohio 1.7 1.0
three 2002 Ohio 3.6 2.0
four 2001 Nevada 2.4 3.0
five 2002 Nevada 2.9 4.0
six 2003 Nevada 3.2 5.0
При присваивании столбцу списка или массива, их длина должна быть той
же, что и длина DataFrame
. Если присваивать объект Series
, то его
метки будут выровнены по индексу DataFrame
, при этом будут
вставляться отсутствующие значения для любых «дыр»:
In [51]: val = pd.Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])
In [52]: frame2['debt'] = val
In [53]: frame2
Out[53]:
year state pop debt
one 2000 Ohio 1.5 NaN
two 2001 Ohio 1.7 -1.2
three 2002 Ohio 3.6 NaN
four 2001 Nevada 2.4 -1.5
five 2002 Nevada 2.9 -1.7
six 2003 Nevada 3.2 NaN
При присваивании отсутствующего столбца в объекте DataFrame
добавится новый столбец. Ключевое слово del
удаляет столбец, как и
для словарей:
In [54]: frame2['eastern'] = frame2.state == 'Ohio'
In [55]: frame2
Out[55]:
year state pop debt eastern
one 2000 Ohio 1.5 NaN True
two 2001 Ohio 1.7 -1.2 True
three 2002 Ohio 3.6 NaN True
four 2001 Nevada 2.4 -1.5 False
five 2002 Nevada 2.9 -1.7 False
six 2003 Nevada 3.2 NaN False
Новый столбец не может быть добавлен с помощью синтаксиса frame2.eastern
.
In [56]: del frame2['eastern']
In [57]: frame2.columns
Out[57]: Index(['year', 'state', 'pop', 'debt'], dtype='object')
Столбец, возвращаемый при индексации DataFrame
, является
представлением данных, а не копией. Таким образом, любые
изменения в объекте Series
будут отражены в объекте
DataFrame
. Столбец можно явно скопировать с помощью метода
Series.copy
.
Другой распространенной формой представления данных является вложенный словарь словарей:
In [58]:
Если вложенный словарь передать в конструктор DataFrame
, pandas
интерпретирует ключи внешнего словаря как столбцы, а внутренние ключи
— как индексы:
In [59]: frame3 = pd.DataFrame(pop)
In [60]: frame3
Out[60]:
Nevada Ohio
2001 2.4 1.7
2002 2.9 3.6
2000 NaN 1.5
Можно транспонировать DataFrame
:
In [61]: frame3.T
Можно задать порядок индексов:
In [62]: pd.DataFrame(pop, index=[2001, 2002, 2003])
Out[62]:
Nevada Ohio
2001 2.4 1.7
2002 2.9 3.6
2003 NaN NaN
Словари рядов обрабатываются практически также:
In [63]: pdata = {'Ohio': frame3['Ohio'][:-1], 'Nevada': frame3['Nevada'][:2]}
In [64]: pd.DataFrame(pdata)
Out[64]:
Nevada Ohio
2000 NaN 1.5
2001 2.4 1.7
Полный список параметров, которые можно передавать в конструктор
DataFrame
, можно найти в таблице pandas:data-struct:tbl:1.
Если для индекса и столбцов DataFrame установлены атрибуты name
, они
также будут отображены:
In [65]: frame3.index.name = 'year'; frame3.columns.name = 'state'
In [66]: frame3
Out[66]:
state Nevada Ohio
year
2001 2.4 1.7
2002 2.9 3.6
2000 NaN 1.5
Как и в случае Series
, атрибут values
возвращает данные,
содержащиеся в DataFrame
, в виде двумерного массива:
In [67]: frame3.values
Out[67]:
array([[2.4, 1.7],
[2.9, 3.6],
[nan, 1.5]])
Таблица 1. Возможные входные данные для конструктора DataFrame
Тип | Примечания |
Двумерный ndarray | Матрица данных, передающаяся с необязательными метками строк и столбцов |
dict массивов, list , tuple | Каждая последовательность становится столбцом в DataFrame . Все последовательности должны быть одинаковой длины |
Структурированный массив (или массив записей) NumPy | Обрабатывается как предыдущий случай |
dict объектов типа Series | Каждое значение становится столбцом. Индексы из каждой серии объединяются вместе, чтобы сформировать индекс строки результата, если не передан явный индекс |
dict объектов типа dict | Каждый внутренний словарь становится столбцом. Ключи объединяются для формирования индекса строки, как в предыдущем случае |
list объектов dict или Series | Каждый элемент становится строкой в DataFrame . Оббъединение ключей dict или индексов Series становится метками столбцов DataFrame |
list объектов list или tuple | Обрабатывается как случай двумерного массива |
DataFrame | Используются индексы DataFrame , если не переданы другие |
маскированный массив NumPy | Как случай двумерного массива, за исключением того, что маскированные значения становятся пропущенными (NA) значениями в итоговом DataFrame |
Index
Объекты типа Index
в pandas
отвечают за хранение меток осей и
других метаданных (таких как имя или имя оси).
Любой массив или другая последовательность меток, которые используются
при создании Series
или DataFrame
, преобразуется в Index
:
In [68]: obj = pd.Series(range(3), index=['a', 'b', 'c'])
In [69]: index = obj.index
In [70]: index
Out[70]: Index(['a', 'b', 'c'], dtype='object')
In [71]: index[1:]
Out[71]: Index(['b', 'c'], dtype='object')
Объекты Index
— неизменяемый тип и не может изменяться
пользователем:
In [72]: index[1] = 'd'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-75-a452e55ce13b> in <module>
----> 1 index[1] = 'd'
/usr/lib/python3.8/site-packages/pandas/core/indexes/base.py in __setitem__(self, key, value)
3907
3908 def __setitem__(self, key, value):
-> 3909 raise TypeError("Index does not support mutable operations")
3910
3911 def __getitem__(self, key):
TypeError: Index does not support mutable operations
Неизменяемость делает более безопасным совместное использование объектов
Index
:
In [73]: labels = pd.Index(np.arange(3))
In [74]: lables
Out[74]: Int64Index([0, 1, 2], dtype='int64')
In [75]: obj2 = pd.Series([1.5, -2.5, 0], index=lables)
In [76]: obj2
Out[76]:
0 1.5
1 -2.5
2 0.0
dtype: float64
In [77]: obj2.index is lables
Out[77]: True
С объектами Index
можно работать как с массивами фиксированного
размера:
In [78]: frame3
Out[78]:
state Nevada Ohio
year
2001 2.4 1.7
2002 2.9 3.6
2000 NaN 1.5
In [79]: frame3.columns
Out[79]: Index(['Nevada', 'Ohio'], dtype='object', name='state')
In [80]: 'Ohio' in frame3.columns
Out[80]: True
In [81]: 2003 in frame3.index
Out[81]: False
В отличие от множеств Python объекты Index
могут содержать
повторяющиеся метки:
In [82]: dup_labels = pd.Index(['foo', 'foo', 'bar', 'bar'])
In [83]: dup_labels
Out[83]: Index(['foo', 'foo', 'bar', 'bar'], dtype='object')
Каждый объект Index
имеет ряд методов и свойств. Некоторые полезные
из них приведены в таблице pandas:data-struct:tbl:2.
Таблица 2. Некоторые методы и свойства Index
Метод | Описание |
append | Добавляет дополнительные объекты Index , создавая новый объект Index |
difference | Возвращает разность множеств как Index |
intersection | Возвращает пересечение множеств |
union | Возвращает объединение множеств |
isin | Возвращает логический массив, указывающий, содержится ли каждое значение в переданной коллекции |
delete | Возвращает новый объект Index с удаленным элементом по индексу i |
drop | Возвращает новый объект Index , удаляя переданные значения |
insert | Возвращает новый объект Index , вставляя по индексу i элемент |
is_monotonic | Возвращает True , если каждый элемент больше либо равен предыдущего |
is_unique | Возвращает True , если объект Index не содержит дупликатов |
unique | Возвращает массив уникальных занчений в объекте Index |