Ядром pandas являются две структуры данных, в которых происходят все операции:
- Series
- Dataframes
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
, а также базовыми операциями для работы с ними, стоит рассмотреть операции, включающие две или более структур.
Гибкие арифметические методы
Уже рассмотренные операции можно выполнять с помощью гибких арифметических методов:
add()
sub()
div()
mul()
Для их вызова нужно использовать другую спецификацию. Например, вместо того чтобы выполнять операцию для двух объектов 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 |