Это короткое введение в мир pandas, ориентированное в основном на новых пользователей. Более сложные рецепты можно найти в Поваренной книге.
Обычно импорт выглядит так и к нему все привыкли:
import numpy as np
import pandas as pd
Подробнее см. Введение в структуры данных pandas
Создание Серии
(Series
) путем передачи питоновского списка позволет pandas создать целочисленный индекс по умолчанию:
s = pd.Series([1, 3, 5, np.nan, 6, 8])
s
0 1.0 1 3.0 2 5.0 3 NaN 4 6.0 5 8.0 dtype: float64
Создание Кадра данных
(DataFrame
) путем передачи массива NumPy с временнЫм индексом и помеченными столбцами:
# указываем начало временнОго периода и число повторений (дни по умолчанию)
dates = pd.date_range('20130101', periods=6)
dates
DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04', '2013-01-05', '2013-01-06'], dtype='datetime64[ns]', freq='D')
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))
df
A | B | C | D | |
---|---|---|---|---|
2013-01-01 | 0.052538 | 0.614095 | -1.162609 | 0.303052 |
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | -0.125083 |
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | -0.442016 |
2013-01-04 | 0.108955 | -1.745538 | 1.205791 | 0.688829 |
2013-01-05 | -1.023572 | -1.364628 | -0.960483 | -0.058651 |
2013-01-06 | 0.542550 | 0.101957 | -0.377727 | -0.246767 |
Создать DataFrame
можно путем передачи питоновского словаря объектов, которые можно преобразовать в серию.
df2 = pd.DataFrame({'A': 1.,
'B': pd.Timestamp('20130102'), # временнАя метка
'C': pd.Series(1, index=list(range(4)), dtype='float32'), # Серия на основе списка
'D': np.array([3] * 4, dtype='int32'), # массив целых чисел NumPy
'E': pd.Categorical(["test", "train", "test", "train"]), # категории
'F': 'foo'})
df2
A | B | C | D | E | F | |
---|---|---|---|---|---|---|
0 | 1.0 | 2013-01-02 | 1.0 | 3 | test | foo |
1 | 1.0 | 2013-01-02 | 1.0 | 3 | train | foo |
2 | 1.0 | 2013-01-02 | 1.0 | 3 | test | foo |
3 | 1.0 | 2013-01-02 | 1.0 | 3 | train | foo |
Столбцы итогового DataFrame
имеют разные типы данных.
df2.dtypes
A float64 B datetime64[ns] C float32 D int32 E category F object dtype: object
Если вы используете IPython
или Jupyter (Lab) Notebook (Colab)
, то по нажатию TAB после точки отобразятся публичные атрибуты объекта (в данном случае DataFrame
):
# Попробуйте убрать комментарий и нажать TAB
# df2.<TAB>
Подробнее см. Документацию по базовой функциональности.
Просмотрим верхние и нижние строки полученного кадра данных:
df.head()
A | B | C | D | |
---|---|---|---|---|
2013-01-01 | 0.052538 | 0.614095 | -1.162609 | 0.303052 |
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | -0.125083 |
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | -0.442016 |
2013-01-04 | 0.108955 | -1.745538 | 1.205791 | 0.688829 |
2013-01-05 | -1.023572 | -1.364628 | -0.960483 | -0.058651 |
df.tail(3) # вывести последние три строки
A | B | C | D | |
---|---|---|---|---|
2013-01-04 | 0.108955 | -1.745538 | 1.205791 | 0.688829 |
2013-01-05 | -1.023572 | -1.364628 | -0.960483 | -0.058651 |
2013-01-06 | 0.542550 | 0.101957 | -0.377727 | -0.246767 |
Отобразим индекс и столбцы:
df.index
DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04', '2013-01-05', '2013-01-06'], dtype='datetime64[ns]', freq='D')
df.columns
Index(['A', 'B', 'C', 'D'], dtype='object')
Метод DataFrame.to_numpy()
представляет данные в виде массива NumPy, на котором строится DataFrame.
df.to_numpy()
array([[ 0.05253805, 0.61409486, -1.16260942, 0.30305152], [ 0.86406465, -1.0483247 , 0.61355486, -0.12508337], [-1.31227091, 0.50544489, -1.25066678, -0.44201611], [ 0.10895534, -1.74553815, 1.20579053, 0.68882904], [-1.02357217, -1.36462828, -0.96048288, -0.05865144], [ 0.54255033, 0.10195697, -0.37772714, -0.24676665]])
Обратите внимание, что эта операция может занять много времени, если ваш DataFrame
имеет столбцы с разными типами данных, что сводится к фундаментальному различию между pandas и NumPy
: массивы NumPy
имеют один тип данных для всего массива, тогда как DataFrames
в pandas имеет один тип данных для каждого столбца. Когда вы вызываете DataFrame.to_numpy()
, pandas определит тип данных NumPy
, который может содержать все типы данных DataFrame
. Этот тип данных может в конечном итоге оказаться объектом (object
, т.е. строкой), что потребует приведения каждого значения к объекту Python.
Наш DataFrame
содержит значения с плавающей точкой, поэтому DataFrame.to_numpy()
сработает быстро и не требует копирования данных.
Для df2, который содержит несколько типов данных, вызов DataFrame.to_numpy()
является относительно дорогостоящим:
df2.to_numpy()
array([[1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'test', 'foo'], [1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'train', 'foo'], [1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'test', 'foo'], [1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'train', 'foo']], dtype=object)
Обратите внимание, что DataFrame.to_numpy()
не включает в вывод метки индекса или столбцов.
Метод describe()
показывает краткую статистическую сводку для данных:
df.describe()
A | B | C | D | |
---|---|---|---|---|
count | 6.000000 | 6.000000 | 6.000000 | 6.000000 |
mean | -0.127956 | -0.489499 | -0.322023 | 0.019894 |
std | 0.863379 | 1.021119 | 1.018746 | 0.409709 |
min | -1.312271 | -1.745538 | -1.250667 | -0.442016 |
25% | -0.754545 | -1.285552 | -1.112078 | -0.216346 |
50% | 0.080747 | -0.473184 | -0.669105 | -0.091867 |
75% | 0.434152 | 0.404573 | 0.365734 | 0.212626 |
max | 0.864065 | 0.614095 | 1.205791 | 0.688829 |
Транспонируем данные:
df.T
2013-01-01 | 2013-01-02 | 2013-01-03 | 2013-01-04 | 2013-01-05 | 2013-01-06 | |
---|---|---|---|---|---|---|
A | 0.052538 | 0.864065 | -1.312271 | 0.108955 | -1.023572 | 0.542550 |
B | 0.614095 | -1.048325 | 0.505445 | -1.745538 | -1.364628 | 0.101957 |
C | -1.162609 | 0.613555 | -1.250667 | 1.205791 | -0.960483 | -0.377727 |
D | 0.303052 | -0.125083 | -0.442016 | 0.688829 | -0.058651 | -0.246767 |
Сортировка по столбцам, см. sort_index()
:
df.sort_index(axis=1, ascending=False) # по умолчанию axis=0, т.е. сортировка по строкам
D | C | B | A | |
---|---|---|---|---|
2013-01-01 | 0.303052 | -1.162609 | 0.614095 | 0.052538 |
2013-01-02 | -0.125083 | 0.613555 | -1.048325 | 0.864065 |
2013-01-03 | -0.442016 | -1.250667 | 0.505445 | -1.312271 |
2013-01-04 | 0.688829 | 1.205791 | -1.745538 | 0.108955 |
2013-01-05 | -0.058651 | -0.960483 | -1.364628 | -1.023572 |
2013-01-06 | -0.246767 | -0.377727 | 0.101957 | 0.542550 |
Сортировка по значениям, см. sort_values()
:
df.sort_values(by='B') # по умолчанию сортировка по индексу, выбрали столбец 'B'
A | B | C | D | |
---|---|---|---|---|
2013-01-04 | 0.108955 | -1.745538 | 1.205791 | 0.688829 |
2013-01-05 | -1.023572 | -1.364628 | -0.960483 | -0.058651 |
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | -0.125083 |
2013-01-06 | 0.542550 | 0.101957 | -0.377727 | -0.246767 |
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | -0.442016 |
2013-01-01 | 0.052538 | 0.614095 | -1.162609 | 0.303052 |
Рекомендуем использовать оптимизированные методы pandas для доступа к данным: .at
, .iat
, .loc
и .iloc
.
Подробнее см. Документацию по индексированию и выбору данных и Мультииндексу.
Выбор столбца, который возвращает Series
, эквивалентно df.A
:
df['A']
2013-01-01 0.052538 2013-01-02 0.864065 2013-01-03 -1.312271 2013-01-04 0.108955 2013-01-05 -1.023572 2013-01-06 0.542550 Freq: D, Name: A, dtype: float64
Выбор с помощью [ ]
, вырезает строки:
df[0:3]
A | B | C | D | |
---|---|---|---|---|
2013-01-01 | 0.052538 | 0.614095 | -1.162609 | 0.303052 |
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | -0.125083 |
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | -0.442016 |
df['20130102':'20130104']
A | B | C | D | |
---|---|---|---|---|
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | -0.125083 |
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | -0.442016 |
2013-01-04 | 0.108955 | -1.745538 | 1.205791 | 0.688829 |
Подробнее см. в Документации
Для получения строки с помощью метки:
df.loc[dates[0]] # метка индекса Timestamp('2013-01-01 00:00:00', freq='D')
A 0.052538 B 0.614095 C -1.162609 D 0.303052 Name: 2013-01-01 00:00:00, dtype: float64
Выбор по нескольким осям:
df.loc[:, ['A', 'B']]
A | B | |
---|---|---|
2013-01-01 | 0.052538 | 0.614095 |
2013-01-02 | 0.864065 | -1.048325 |
2013-01-03 | -1.312271 | 0.505445 |
2013-01-04 | 0.108955 | -1.745538 |
2013-01-05 | -1.023572 | -1.364628 |
2013-01-06 | 0.542550 | 0.101957 |
При отображении срезов меток включаются обе конечные точки:
df.loc['20130102':'20130104', ['A', 'B']]
A | B | |
---|---|---|
2013-01-02 | 0.864065 | -1.048325 |
2013-01-03 | -1.312271 | 0.505445 |
2013-01-04 | 0.108955 | -1.745538 |
Уменьшение размерности возвращаемого объекта:
df.loc['20130102', ['A', 'B']]
A 0.864065 B -1.048325 Name: 2013-01-02 00:00:00, dtype: float64
Для получения скалярного значения:
df.loc[dates[0], 'A']
0.0525380518675587
Для получения быстрого доступа к скаляру (эквивалентно предыдущему методу):
df.at[dates[0], 'A']
0.0525380518675587
Подробнее см. в Документации
Выбор позиции с помощью целых чисел:
df.iloc[3]
A 0.108955 B -1.745538 C 1.205791 D 0.688829 Name: 2013-01-04 00:00:00, dtype: float64
По целочисленным срезам, действующим аналогично NumPy / Python, т.е. правое граничное значение не включается:
df.iloc[3:5, 0:2]
A | B | |
---|---|---|
2013-01-04 | 0.108955 | -1.745538 |
2013-01-05 | -1.023572 | -1.364628 |
По спискам целочисленных позиций, аналогично стилю NumPy / Python:
df.iloc[[1, 2, 4], [0, 2]]
A | C | |
---|---|---|
2013-01-02 | 0.864065 | 0.613555 |
2013-01-03 | -1.312271 | -1.250667 |
2013-01-05 | -1.023572 | -0.960483 |
Для явного создания среза строк:
df.iloc[1:3, :]
A | B | C | D | |
---|---|---|---|---|
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | -0.125083 |
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | -0.442016 |
Для явного создания среза столбцов:
df.iloc[:, 1:3]
B | C | |
---|---|---|
2013-01-01 | 0.614095 | -1.162609 |
2013-01-02 | -1.048325 | 0.613555 |
2013-01-03 | 0.505445 | -1.250667 |
2013-01-04 | -1.745538 | 1.205791 |
2013-01-05 | -1.364628 | -0.960483 |
2013-01-06 | 0.101957 | -0.377727 |
Для явного получения значений:
df.iloc[1, 1]
-1.048324699463767
Для получения быстрого доступа к скаляру (эквивалентно предыдущему методу):
df.iat[1, 1]
-1.048324699463767
Использование значений одного столбца для выбора данных:
df[df['A'] > 0]
A | B | C | D | |
---|---|---|---|---|
2013-01-01 | 0.052538 | 0.614095 | -1.162609 | 0.303052 |
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | -0.125083 |
2013-01-04 | 0.108955 | -1.745538 | 1.205791 | 0.688829 |
2013-01-06 | 0.542550 | 0.101957 | -0.377727 | -0.246767 |
Выбор значений из DataFrame
, для которых выполняется логическое условие:
df[df > 0]
A | B | C | D | |
---|---|---|---|---|
2013-01-01 | 0.052538 | 0.614095 | NaN | 0.303052 |
2013-01-02 | 0.864065 | NaN | 0.613555 | NaN |
2013-01-03 | NaN | 0.505445 | NaN | NaN |
2013-01-04 | 0.108955 | NaN | 1.205791 | 0.688829 |
2013-01-05 | NaN | NaN | NaN | NaN |
2013-01-06 | 0.542550 | 0.101957 | NaN | NaN |
Использование метода isin()
для фильтрации:
df2 = df.copy() # создаем копию исходгого кадра данных
df2['E'] = ['one', 'one', 'two', 'three', 'four', 'three'] # добавляем столбец
df2
A | B | C | D | E | |
---|---|---|---|---|---|
2013-01-01 | 0.052538 | 0.614095 | -1.162609 | 0.303052 | one |
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | -0.125083 | one |
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | -0.442016 | two |
2013-01-04 | 0.108955 | -1.745538 | 1.205791 | 0.688829 | three |
2013-01-05 | -1.023572 | -1.364628 | -0.960483 | -0.058651 | four |
2013-01-06 | 0.542550 | 0.101957 | -0.377727 | -0.246767 | three |
df2[df2['E'].isin(['two', 'four'])] # фильтруем
A | B | C | D | E | |
---|---|---|---|---|---|
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | -0.442016 | two |
2013-01-05 | -1.023572 | -1.364628 | -0.960483 | -0.058651 | four |
При добавлении нового столбца данные автоматически выравниваются по индексам:
s1 = pd.Series([1, 2, 3, 4, 5, 6], index=pd.date_range('20130102', periods=6))
s1
2013-01-02 1 2013-01-03 2 2013-01-04 3 2013-01-05 4 2013-01-06 5 2013-01-07 6 Freq: D, dtype: int64
df['F'] = s1 # отсутствующие значения после выравнивания заменились NaN
df
A | B | C | D | F | |
---|---|---|---|---|---|
2013-01-01 | 0.052538 | 0.614095 | -1.162609 | 0.303052 | NaN |
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | -0.125083 | 1.0 |
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | -0.442016 | 2.0 |
2013-01-04 | 0.108955 | -1.745538 | 1.205791 | 0.688829 | 3.0 |
2013-01-05 | -1.023572 | -1.364628 | -0.960483 | -0.058651 | 4.0 |
2013-01-06 | 0.542550 | 0.101957 | -0.377727 | -0.246767 | 5.0 |
Установка значений по метке:
df.iat[0, 1] = 0
df
A | B | C | D | F | |
---|---|---|---|---|---|
2013-01-01 | 0.052538 | 0.000000 | -1.162609 | 0.303052 | NaN |
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | -0.125083 | 1.0 |
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | -0.442016 | 2.0 |
2013-01-04 | 0.108955 | -1.745538 | 1.205791 | 0.688829 | 3.0 |
2013-01-05 | -1.023572 | -1.364628 | -0.960483 | -0.058651 | 4.0 |
2013-01-06 | 0.542550 | 0.101957 | -0.377727 | -0.246767 | 5.0 |
Установка значений путем присвоения массива NumPy:
df.loc[:, 'D'] = np.array([5] * len(df))
df
A | B | C | D | F | |
---|---|---|---|---|---|
2013-01-01 | 0.052538 | 0.000000 | -1.162609 | 5 | NaN |
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | 5 | 1.0 |
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | 5 | 2.0 |
2013-01-04 | 0.108955 | -1.745538 | 1.205791 | 5 | 3.0 |
2013-01-05 | -1.023572 | -1.364628 | -0.960483 | 5 | 4.0 |
2013-01-06 | 0.542550 | 0.101957 | -0.377727 | 5 | 5.0 |
Операция where
с помощью присвоения:
df2 = df.copy() # копируем кадр данных
df2
A | B | C | D | F | |
---|---|---|---|---|---|
2013-01-01 | 0.052538 | 0.000000 | -1.162609 | 5 | NaN |
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | 5 | 1.0 |
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | 5 | 2.0 |
2013-01-04 | 0.108955 | -1.745538 | 1.205791 | 5 | 3.0 |
2013-01-05 | -1.023572 | -1.364628 | -0.960483 | 5 | 4.0 |
2013-01-06 | 0.542550 | 0.101957 | -0.377727 | 5 | 5.0 |
df2[df2 > 0] = -df2 # все положительные превращаем в отрицательные
df2
A | B | C | D | F | |
---|---|---|---|---|---|
2013-01-01 | -0.052538 | 0.000000 | -1.162609 | -5 | NaN |
2013-01-02 | -0.864065 | -1.048325 | -0.613555 | -5 | -1.0 |
2013-01-03 | -1.312271 | -0.505445 | -1.250667 | -5 | -2.0 |
2013-01-04 | -0.108955 | -1.745538 | -1.205791 | -5 | -3.0 |
2013-01-05 | -1.023572 | -1.364628 | -0.960483 | -5 | -4.0 |
2013-01-06 | -0.542550 | -0.101957 | -0.377727 | -5 | -5.0 |
pandas в основном использует значение np.nan
для представления отсутствующих данных. По умолчанию они не включается в вычисления, см. подробнее в Документации
Повторное индексирование позволяет изменить/добавить/удалить индекс по указанной оси. Метод возвращает копию данных.
df1 = df.reindex(index=dates[0:4], columns=list(df.columns) + ['E'])
df1
A | B | C | D | F | E | |
---|---|---|---|---|---|---|
2013-01-01 | 0.052538 | 0.000000 | -1.162609 | 5 | NaN | NaN |
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | 5 | 1.0 | NaN |
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | 5 | 2.0 | NaN |
2013-01-04 | 0.108955 | -1.745538 | 1.205791 | 5 | 3.0 | NaN |
df1.loc[dates[0]:dates[1], 'E'] = 1
df1
A | B | C | D | F | E | |
---|---|---|---|---|---|---|
2013-01-01 | 0.052538 | 0.000000 | -1.162609 | 5 | NaN | 1.0 |
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | 5 | 1.0 | 1.0 |
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | 5 | 2.0 | NaN |
2013-01-04 | 0.108955 | -1.745538 | 1.205791 | 5 | 3.0 | NaN |
Чтобы удалить строки, в которых отсутствуют данные, см. dropna()
:
df1.dropna() # how='any', axis=0 по умолчанию, т.е. удаляются все строки с пропущенными данными
A | B | C | D | F | E | |
---|---|---|---|---|---|---|
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | 5 | 1.0 | 1.0 |
Заполнение недостающих данных:
df1.fillna(value=5)
A | B | C | D | F | E | |
---|---|---|---|---|---|---|
2013-01-01 | 0.052538 | 0.000000 | -1.162609 | 5 | 5.0 | 1.0 |
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | 5 | 1.0 | 1.0 |
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | 5 | 2.0 | 5.0 |
2013-01-04 | 0.108955 | -1.745538 | 1.205791 | 5 | 3.0 | 5.0 |
Чтобы получить логическую маску, в которой значениями являются nan.
pd.isna(df1)
A | B | C | D | F | E | |
---|---|---|---|---|---|---|
2013-01-01 | False | False | False | False | True | False |
2013-01-02 | False | False | False | False | False | False |
2013-01-03 | False | False | False | False | False | True |
2013-01-04 | False | False | False | False | False | True |
См. в Документации
Операции в целом исключают пропущенные данные.
Выполнение описательной статистики:
df.mean()
A -0.127956 B -0.591848 C -0.322023 D 5.000000 F 3.000000 dtype: float64
Та же операция на другой оси:
df.mean(1)
2013-01-01 0.972482 2013-01-02 1.285859 2013-01-03 0.988501 2013-01-04 1.513842 2013-01-05 1.130263 2013-01-06 2.053356 Freq: D, dtype: float64
Операции с объектами разной размерности требуют выравнивания. pandas автоматически транслируют по указанному измерению.
s = pd.Series([1, 3, 5, np.nan, 6, 8], index=dates).shift(2) # сдвигаем индекс
s
2013-01-01 NaN 2013-01-02 NaN 2013-01-03 1.0 2013-01-04 3.0 2013-01-05 5.0 2013-01-06 NaN Freq: D, dtype: float64
df
A | B | C | D | F | |
---|---|---|---|---|---|
2013-01-01 | 0.052538 | 0.000000 | -1.162609 | 5 | NaN |
2013-01-02 | 0.864065 | -1.048325 | 0.613555 | 5 | 1.0 |
2013-01-03 | -1.312271 | 0.505445 | -1.250667 | 5 | 2.0 |
2013-01-04 | 0.108955 | -1.745538 | 1.205791 | 5 | 3.0 |
2013-01-05 | -1.023572 | -1.364628 | -0.960483 | 5 | 4.0 |
2013-01-06 | 0.542550 | 0.101957 | -0.377727 | 5 | 5.0 |
df.sub(s, axis=0) # https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.sub.html
A | B | C | D | F | |
---|---|---|---|---|---|
2013-01-01 | NaN | NaN | NaN | NaN | NaN |
2013-01-02 | NaN | NaN | NaN | NaN | NaN |
2013-01-03 | -2.312271 | -0.494555 | -2.250667 | 4.0 | 1.0 |
2013-01-04 | -2.891045 | -4.745538 | -1.794209 | 2.0 | 0.0 |
2013-01-05 | -6.023572 | -6.364628 | -5.960483 | 0.0 | -1.0 |
2013-01-06 | NaN | NaN | NaN | NaN | NaN |
Применение функций к данным:
df.apply(np.cumsum)
A | B | C | D | F | |
---|---|---|---|---|---|
2013-01-01 | 0.052538 | 0.000000 | -1.162609 | 5 | NaN |
2013-01-02 | 0.916603 | -1.048325 | -0.549055 | 10 | 1.0 |
2013-01-03 | -0.395668 | -0.542880 | -1.799721 | 15 | 3.0 |
2013-01-04 | -0.286713 | -2.288418 | -0.593931 | 20 | 6.0 |
2013-01-05 | -1.310285 | -3.653046 | -1.554414 | 25 | 10.0 |
2013-01-06 | -0.767735 | -3.551089 | -1.932141 | 30 | 15.0 |
df.apply(lambda x: x.max() - x.min())
A 2.176336 B 2.250983 C 2.456457 D 0.000000 F 4.000000 dtype: float64
Подробнее см. в Документации
s = pd.Series(np.random.randint(0, 7, size=10))
s
0 5 1 6 2 2 3 6 4 5 5 2 6 4 7 4 8 2 9 5 dtype: int64
s.value_counts()
5 3 2 3 6 2 4 2 dtype: int64
Series оснащен набором методов в атрибуте str
для обработки строк, которые упрощают работу с каждым элементом массива. Обратите внимание, что сопоставление с образцом (pattern-matching) в str
обычно использует регулярные выражения по умолчанию (а в некоторых случаях всегда использует их), см. в Документации.
s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca', np.nan, 'CABA', 'dog', 'cat'])
s
0 A 1 B 2 C 3 Aaba 4 Baca 5 NaN 6 CABA 7 dog 8 cat dtype: object
s.str.lower()
0 a 1 b 2 c 3 aaba 4 baca 5 NaN 6 caba 7 dog 8 cat dtype: object
pandas предоставляет различные средства для простого объединения объектов Series
и DataFrame
с различными видами логики множеств для индексов и функциональности реляционной алгебры в случае операций типа соединения (join
) / слияния (merge
), см. в Документации.
Объединение объектов pandas вместе с помощью concat()
:
df = pd.DataFrame(np.random.randn(10, 4))
df
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 1.002693 | -0.636190 | -0.299104 | 0.400296 |
1 | 0.613168 | -1.023674 | -1.280330 | 0.837075 |
2 | 0.414970 | -0.772923 | -0.560176 | -0.854781 |
3 | 0.889952 | -0.562532 | 0.509436 | -1.455043 |
4 | 1.927648 | 0.257844 | -2.507807 | -0.883411 |
5 | -0.321618 | -0.780484 | -0.155023 | 0.530323 |
6 | 0.743151 | 0.720452 | -1.127323 | -0.232548 |
7 | -1.352597 | 1.310645 | -0.349348 | 1.754640 |
8 | -1.744953 | 0.087623 | -0.916006 | -0.617917 |
9 | 2.424113 | 0.992514 | 2.348996 | -0.370691 |
pieces = [df[:3], df[3:7], df[7:]] # разбиваем на части
pd.concat(pieces)
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 1.002693 | -0.636190 | -0.299104 | 0.400296 |
1 | 0.613168 | -1.023674 | -1.280330 | 0.837075 |
2 | 0.414970 | -0.772923 | -0.560176 | -0.854781 |
3 | 0.889952 | -0.562532 | 0.509436 | -1.455043 |
4 | 1.927648 | 0.257844 | -2.507807 | -0.883411 |
5 | -0.321618 | -0.780484 | -0.155023 | 0.530323 |
6 | 0.743151 | 0.720452 | -1.127323 | -0.232548 |
7 | -1.352597 | 1.310645 | -0.349348 | 1.754640 |
8 | -1.744953 | 0.087623 | -0.916006 | -0.617917 |
9 | 2.424113 | 0.992514 | 2.348996 | -0.370691 |
Добавление столбца в DataFrame
выполняется относительно быстро. Однако для добавления строки требуется создание копии, и это может стать трудозтратной операцией. Рекомендуем передавать предварительно созданный список записей в конструктор DataFrame
вместо создания DataFrame
путем итеративного добавления к нему записей. Подробнее см. в Документации.
Слияние в стиле SQL
, см. в Документации.
left = pd.DataFrame({'key': ['foo', 'foo'], 'lval': [1, 2]})
left
key | lval | |
---|---|---|
0 | foo | 1 |
1 | foo | 2 |
right = pd.DataFrame({'key': ['foo', 'foo'], 'rval': [4, 5]})
right
key | rval | |
---|---|---|
0 | foo | 4 |
1 | foo | 5 |
pd.merge(left, right, on='key')
key | lval | rval | |
---|---|---|---|
0 | foo | 1 | 4 |
1 | foo | 1 | 5 |
2 | foo | 2 | 4 |
3 | foo | 2 | 5 |
Другой пример, который можно привести:
left = pd.DataFrame({'key': ['foo', 'bar'], 'lval': [1, 2]})
left
key | lval | |
---|---|---|
0 | foo | 1 |
1 | bar | 2 |
right = pd.DataFrame({'key': ['foo', 'bar'], 'rval': [4, 5]})
right
key | rval | |
---|---|---|
0 | foo | 4 |
1 | bar | 5 |
pd.merge(left, right, on='key')
key | lval | rval | |
---|---|---|---|
0 | foo | 1 | 4 |
1 | bar | 2 | 5 |
Под группировкой ("group by"
) понимаем процесс, включающий один или несколько следующих шагов:
Splitting
) данных на группы по некоторым критериям.Applying
) функции к каждой группе.Combining
) результатов в структуру данных.Подробнее см. в Документации
df = pd.DataFrame({'A': ['foo', 'bar', 'foo', 'bar',
'foo', 'bar', 'foo', 'foo'],
'B': ['one', 'one', 'two', 'three',
'two', 'two', 'one', 'three'],
'C': np.random.randn(8),
'D': np.random.randn(8)})
df
A | B | C | D | |
---|---|---|---|---|
0 | foo | one | -0.195637 | -0.164797 |
1 | bar | one | -1.318484 | 2.662692 |
2 | foo | two | -0.793403 | -0.310082 |
3 | bar | three | 0.910756 | -0.444571 |
4 | foo | two | -1.009964 | -0.385792 |
5 | bar | two | -0.968159 | -0.307006 |
6 | foo | one | 0.554111 | -0.312931 |
7 | foo | three | -0.491810 | -0.022793 |
Группировка, а затем применение функции sum()
к полученным группам.
df.groupby('A').sum()
C | D | |
---|---|---|
A | ||
bar | -1.375887 | 1.911116 |
foo | -1.936704 | -1.196394 |
Группировка по нескольким столбцам образует иерархический (мультииндекс) индекс, и мы снова можем применить функцию sum()
.
df.groupby(['A', 'B']).sum()
C | D | ||
---|---|---|---|
A | B | ||
bar | one | -1.318484 | 2.662692 |
three | 0.910756 | -0.444571 | |
two | -0.968159 | -0.307006 | |
foo | one | 0.358474 | -0.477728 |
three | -0.491810 | -0.022793 | |
two | -1.803367 | -0.695873 |
См. Документацию про иерархическую индексацию и изменение формы.
tuples = list(zip(*[['bar', 'bar', 'baz', 'baz',
'foo', 'foo', 'qux', 'qux'],
['one', 'two', 'one', 'two',
'one', 'two', 'one', 'two']]))
tuples
[('bar', 'one'), ('bar', 'two'), ('baz', 'one'), ('baz', 'two'), ('foo', 'one'), ('foo', 'two'), ('qux', 'one'), ('qux', 'two')]
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
index
MultiIndex([('bar', 'one'), ('bar', 'two'), ('baz', 'one'), ('baz', 'two'), ('foo', 'one'), ('foo', 'two'), ('qux', 'one'), ('qux', 'two')], names=['first', 'second'])
df = pd.DataFrame(np.random.randn(8, 2), index=index, columns=['A', 'B'])
df
A | B | ||
---|---|---|---|
first | second | ||
bar | one | 1.697091 | 0.902926 |
two | 1.902566 | 1.088459 | |
baz | one | 0.352447 | -0.304715 |
two | -0.807370 | 1.169234 | |
foo | one | -0.603642 | 0.827633 |
two | -0.807780 | -1.785962 | |
qux | one | -0.168225 | 1.713321 |
two | -0.278263 | 1.358103 |
df2 = df[:4]
df2
A | B | ||
---|---|---|---|
first | second | ||
bar | one | 1.697091 | 0.902926 |
two | 1.902566 | 1.088459 | |
baz | one | 0.352447 | -0.304715 |
two | -0.807370 | 1.169234 |
Метод stack()
"сжимает" уровень в столбцах DataFrame.
stacked = df2.stack()
stacked
first second bar one A 1.697091 B 0.902926 two A 1.902566 B 1.088459 baz one A 0.352447 B -0.304715 two A -0.807370 B 1.169234 dtype: float64
С "уложенными" ("stacked"
) DataFrame или Series (имеющими MultiIndex в качестве индекса) обратная операция - unstack()
, которая по умолчанию распаковывает последний уровень:
stacked.unstack()
A | B | ||
---|---|---|---|
first | second | ||
bar | one | 1.697091 | 0.902926 |
two | 1.902566 | 1.088459 | |
baz | one | 0.352447 | -0.304715 |
two | -0.807370 | 1.169234 |
stacked.unstack(1)
second | one | two | |
---|---|---|---|
first | |||
bar | A | 1.697091 | 1.902566 |
B | 0.902926 | 1.088459 | |
baz | A | 0.352447 | -0.807370 |
B | -0.304715 | 1.169234 |
stacked.unstack(0)
first | bar | baz | |
---|---|---|---|
second | |||
one | A | 1.697091 | 0.352447 |
B | 0.902926 | -0.304715 | |
two | A | 1.902566 | -0.807370 |
B | 1.088459 | 1.169234 |
См. секцию Документации
df = pd.DataFrame({'A': ['one', 'one', 'two', 'three'] * 3,
'B': ['A', 'B', 'C'] * 4,
'C': ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 2,
'D': np.random.randn(12),
'E': np.random.randn(12)})
df
A | B | C | D | E | |
---|---|---|---|---|---|
0 | one | A | foo | 0.953930 | -0.012873 |
1 | one | B | foo | 1.624421 | -0.457593 |
2 | two | C | foo | -1.022637 | 1.260885 |
3 | three | A | bar | 0.458661 | -1.412552 |
4 | one | B | bar | -0.757102 | -0.165448 |
5 | one | C | bar | -0.045363 | 0.759340 |
6 | two | A | foo | -0.392974 | 0.081717 |
7 | three | B | foo | 1.531449 | 2.305852 |
8 | one | C | foo | 0.300884 | -1.061149 |
9 | one | A | bar | 1.066499 | 1.770650 |
10 | two | B | bar | -0.508883 | -1.239101 |
11 | three | C | bar | 0.847643 | 0.443952 |
Мы можем очень легко создать сводные таблицы из этих данных:
pd.pivot_table(df, values='D', index=['A', 'B'], columns=['C'])
C | bar | foo | |
---|---|---|---|
A | B | ||
one | A | 1.066499 | 0.953930 |
B | -0.757102 | 1.624421 | |
C | -0.045363 | 0.300884 | |
three | A | 0.458661 | NaN |
B | NaN | 1.531449 | |
C | 0.847643 | NaN | |
two | A | NaN | -0.392974 |
B | -0.508883 | NaN | |
C | NaN | -1.022637 |
pandas имеет простые, мощные и эффективные функции для выполнения операций передискретизации во время преобразования частоты (например, преобразование секундных данных в 5-минутные данные). См. документацию по временным рядам.
rng = pd.date_range('1/1/2012', periods=100, freq='S')
rng[:10]
DatetimeIndex(['2012-01-01 00:00:00', '2012-01-01 00:00:01', '2012-01-01 00:00:02', '2012-01-01 00:00:03', '2012-01-01 00:00:04', '2012-01-01 00:00:05', '2012-01-01 00:00:06', '2012-01-01 00:00:07', '2012-01-01 00:00:08', '2012-01-01 00:00:09'], dtype='datetime64[ns]', freq='S')
ts = pd.Series(np.random.randint(0, 500, len(rng)), index=rng)
ts[:10]
2012-01-01 00:00:00 349 2012-01-01 00:00:01 208 2012-01-01 00:00:02 391 2012-01-01 00:00:03 105 2012-01-01 00:00:04 65 2012-01-01 00:00:05 185 2012-01-01 00:00:06 306 2012-01-01 00:00:07 257 2012-01-01 00:00:08 137 2012-01-01 00:00:09 85 Freq: S, dtype: int64
ts.resample('5Min').sum()
2012-01-01 25344 Freq: 5T, dtype: int64
Представление часового пояса:
rng = pd.date_range('3/6/2012 00:00', periods=5, freq='D')
rng
DatetimeIndex(['2012-03-06', '2012-03-07', '2012-03-08', '2012-03-09', '2012-03-10'], dtype='datetime64[ns]', freq='D')
ts = pd.Series(np.random.randn(len(rng)), rng)
ts
2012-03-06 -1.104564 2012-03-07 -1.216496 2012-03-08 -0.202999 2012-03-09 1.117123 2012-03-10 -0.419264 Freq: D, dtype: float64
ts
2012-03-06 -1.104564 2012-03-07 -1.216496 2012-03-08 -0.202999 2012-03-09 1.117123 2012-03-10 -0.419264 Freq: D, dtype: float64
ts_utc = ts.tz_localize('UTC')
ts_utc
2012-03-06 00:00:00+00:00 -1.104564 2012-03-07 00:00:00+00:00 -1.216496 2012-03-08 00:00:00+00:00 -0.202999 2012-03-09 00:00:00+00:00 1.117123 2012-03-10 00:00:00+00:00 -0.419264 Freq: D, dtype: float64
Преобразование в другой часовой пояс:
ts_utc.tz_convert('US/Eastern')
2012-03-05 19:00:00-05:00 -1.104564 2012-03-06 19:00:00-05:00 -1.216496 2012-03-07 19:00:00-05:00 -0.202999 2012-03-08 19:00:00-05:00 1.117123 2012-03-09 19:00:00-05:00 -0.419264 Freq: D, dtype: float64
Преобразование между представлениями промежутка времени:
rng = pd.date_range('1/1/2012', periods=5, freq='M')
rng
DatetimeIndex(['2012-01-31', '2012-02-29', '2012-03-31', '2012-04-30', '2012-05-31'], dtype='datetime64[ns]', freq='M')
ts = pd.Series(np.random.randn(len(rng)), index=rng)
ts
2012-01-31 0.452764 2012-02-29 0.028134 2012-03-31 1.563873 2012-04-30 -1.632886 2012-05-31 0.601460 Freq: M, dtype: float64
ps = ts.to_period()
ps
2012-01 0.452764 2012-02 0.028134 2012-03 1.563873 2012-04 -1.632886 2012-05 0.601460 Freq: M, dtype: float64
ps.to_timestamp()
2012-01-01 0.452764 2012-02-01 0.028134 2012-03-01 1.563873 2012-04-01 -1.632886 2012-05-01 0.601460 Freq: MS, dtype: float64
Преобразование между периодом и меткой времени позволяет использовать некоторые удобные арифметические функции. В следующем примере мы преобразуем ежеквартальную частоту с годом, заканчивающимся в ноябре, в 9 утра конца месяца, следующего за концом квартала:
prng = pd.period_range('1990Q1', '2000Q4', freq='Q-NOV')
prng
PeriodIndex(['1990Q1', '1990Q2', '1990Q3', '1990Q4', '1991Q1', '1991Q2', '1991Q3', '1991Q4', '1992Q1', '1992Q2', '1992Q3', '1992Q4', '1993Q1', '1993Q2', '1993Q3', '1993Q4', '1994Q1', '1994Q2', '1994Q3', '1994Q4', '1995Q1', '1995Q2', '1995Q3', '1995Q4', '1996Q1', '1996Q2', '1996Q3', '1996Q4', '1997Q1', '1997Q2', '1997Q3', '1997Q4', '1998Q1', '1998Q2', '1998Q3', '1998Q4', '1999Q1', '1999Q2', '1999Q3', '1999Q4', '2000Q1', '2000Q2', '2000Q3', '2000Q4'], dtype='period[Q-NOV]', freq='Q-NOV')
ts = pd.Series(np.random.randn(len(prng)), prng)
ts[:10]
1990Q1 0.419238 1990Q2 1.048590 1990Q3 -0.484074 1990Q4 -0.333682 1991Q1 -0.241954 1991Q2 2.059292 1991Q3 0.304826 1991Q4 0.465235 1992Q1 -0.647790 1992Q2 -0.015821 Freq: Q-NOV, dtype: float64
ts.index = (prng.asfreq('M', 'e') + 1).asfreq('H', 's') + 9
ts[:10]
1990-03-01 09:00 0.419238 1990-06-01 09:00 1.048590 1990-09-01 09:00 -0.484074 1990-12-01 09:00 -0.333682 1991-03-01 09:00 -0.241954 1991-06-01 09:00 2.059292 1991-09-01 09:00 0.304826 1991-12-01 09:00 0.465235 1992-03-01 09:00 -0.647790 1992-06-01 09:00 -0.015821 Freq: H, dtype: float64
ts.head()
1990-03-01 09:00 0.419238 1990-06-01 09:00 1.048590 1990-09-01 09:00 -0.484074 1990-12-01 09:00 -0.333682 1991-03-01 09:00 -0.241954 Freq: H, dtype: float64
pandas могут включать категориальные данные в DataFrame
, см. введение в категории и документацию по API.
df = pd.DataFrame({"id": [1, 2, 3, 4, 5, 6],
"raw_grade": ['a', 'b', 'b', 'a', 'a', 'e']})
Преобразуйте необработанные оценки в категориальный тип данных.
df["grade"] = df["raw_grade"].astype("category")
df["grade"]
0 a 1 b 2 b 3 a 4 a 5 e Name: grade, dtype: category Categories (3, object): ['a', 'b', 'e']
Переименуйте категории в более выразительные имена (присвоение Series.cat.categories()
на месте!)
df["grade"] = df["grade"].cat.set_categories(["very bad", "bad", "medium", "good", "very good"])
df["grade"]
0 NaN 1 NaN 2 NaN 3 NaN 4 NaN 5 NaN Name: grade, dtype: category Categories (5, object): ['very bad', 'bad', 'medium', 'good', 'very good']
Сортировка осуществляется по категориям, а не в лексическом порядке.
df.sort_values(by="grade")
id | raw_grade | grade | |
---|---|---|---|
0 | 1 | a | NaN |
1 | 2 | b | NaN |
2 | 3 | b | NaN |
3 | 4 | a | NaN |
4 | 5 | a | NaN |
5 | 6 | e | NaN |
При группировке по столбцу категорий также отображаются пустые категории.
df.groupby("grade").size()
grade very bad 0 bad 0 medium 0 good 0 very good 0 dtype: int64
Подробнее в Документации
Используем стандартное соглашение для ссылки на API matplotlib
:
import matplotlib.pyplot as plt
ts = pd.Series(np.random.randn(1000),
index=pd.date_range('1/1/2000', periods=1000))
ts
2000-01-01 -0.991259 2000-01-02 0.789683 2000-01-03 1.764631 2000-01-04 -1.515114 2000-01-05 -1.137938 ... 2002-09-22 -0.376039 2002-09-23 0.354575 2002-09-24 -0.410905 2002-09-25 -0.164925 2002-09-26 0.447177 Freq: D, Length: 1000, dtype: float64
ts = ts.cumsum()
ts
2000-01-01 -0.991259 2000-01-02 -0.201576 2000-01-03 1.563054 2000-01-04 0.047940 2000-01-05 -1.089999 ... 2002-09-22 0.566901 2002-09-23 0.921475 2002-09-24 0.510570 2002-09-25 0.345645 2002-09-26 0.792823 Freq: D, Length: 1000, dtype: float64
ts.plot();
В DataFrame
метод plot()
удобен для построения всех столбцов с метками:
df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index,
columns=['A', 'B', 'C', 'D'])
df.head()
A | B | C | D | |
---|---|---|---|---|
2000-01-01 | 0.236994 | -0.355121 | 0.136809 | 0.572371 |
2000-01-02 | -0.199658 | 0.995229 | -0.210597 | 0.278050 |
2000-01-03 | -0.587741 | 1.419077 | -0.089289 | -0.757641 |
2000-01-04 | 0.948900 | 1.766224 | 0.699568 | -2.395337 |
2000-01-05 | 0.401399 | -0.051646 | 0.194865 | 1.561328 |
df = df.cumsum()
df.head()
A | B | C | D | |
---|---|---|---|---|
2000-01-01 | 0.236994 | -0.355121 | 0.136809 | 0.572371 |
2000-01-02 | 0.037336 | 0.640108 | -0.073788 | 0.850422 |
2000-01-03 | -0.550405 | 2.059185 | -0.163077 | 0.092781 |
2000-01-04 | 0.398495 | 3.825408 | 0.536491 | -2.302556 |
2000-01-05 | 0.799894 | 3.773762 | 0.731356 | -0.741228 |
df.plot(legend='best');
df.to_csv('foo.csv')
pd.read_csv('foo.csv')
Unnamed: 0 | A | B | C | D | |
---|---|---|---|---|---|
0 | 2000-01-01 | 0.236994 | -0.355121 | 0.136809 | 0.572371 |
1 | 2000-01-02 | 0.037336 | 0.640108 | -0.073788 | 0.850422 |
2 | 2000-01-03 | -0.550405 | 2.059185 | -0.163077 | 0.092781 |
3 | 2000-01-04 | 0.398495 | 3.825408 | 0.536491 | -2.302556 |
4 | 2000-01-05 | 0.799894 | 3.773762 | 0.731356 | -0.741228 |
... | ... | ... | ... | ... | ... |
995 | 2002-09-22 | -47.114186 | -2.384106 | -43.736190 | -55.759428 |
996 | 2002-09-23 | -47.909157 | -2.196346 | -43.260616 | -54.962861 |
997 | 2002-09-24 | -46.155662 | -2.505858 | -43.390343 | -56.444827 |
998 | 2002-09-25 | -44.870207 | -2.818082 | -41.770450 | -56.236028 |
999 | 2002-09-26 | -45.756302 | -1.328592 | -41.348363 | -55.779009 |
1000 rows × 5 columns
см. про чтение и запись в HDFStores
Запись в HDF5
хранилище:
df.to_hdf('foo.h5', 'df')
Чтение из HDF5
хранилища:
pd.read_hdf('foo.h5', 'df')
A | B | C | D | |
---|---|---|---|---|
2000-01-01 | 0.236994 | -0.355121 | 0.136809 | 0.572371 |
2000-01-02 | 0.037336 | 0.640108 | -0.073788 | 0.850422 |
2000-01-03 | -0.550405 | 2.059185 | -0.163077 | 0.092781 |
2000-01-04 | 0.398495 | 3.825408 | 0.536491 | -2.302556 |
2000-01-05 | 0.799894 | 3.773762 | 0.731356 | -0.741228 |
... | ... | ... | ... | ... |
2002-09-22 | -47.114186 | -2.384106 | -43.736190 | -55.759428 |
2002-09-23 | -47.909157 | -2.196346 | -43.260616 | -54.962861 |
2002-09-24 | -46.155662 | -2.505858 | -43.390343 | -56.444827 |
2002-09-25 | -44.870207 | -2.818082 | -41.770450 | -56.236028 |
2002-09-26 | -45.756302 | -1.328592 | -41.348363 | -55.779009 |
1000 rows × 4 columns
Запись в excel файл:
df.to_excel('foo.xlsx', sheet_name='Sheet1')
Чтение из excel файла:
pd.read_excel('foo.xlsx', 'Sheet1', index_col=None, na_values=['NA'])
Unnamed: 0 | A | B | C | D | |
---|---|---|---|---|---|
0 | 2000-01-01 | 0.236994 | -0.355121 | 0.136809 | 0.572371 |
1 | 2000-01-02 | 0.037336 | 0.640108 | -0.073788 | 0.850422 |
2 | 2000-01-03 | -0.550405 | 2.059185 | -0.163077 | 0.092781 |
3 | 2000-01-04 | 0.398495 | 3.825408 | 0.536491 | -2.302556 |
4 | 2000-01-05 | 0.799894 | 3.773762 | 0.731356 | -0.741228 |
... | ... | ... | ... | ... | ... |
995 | 2002-09-22 | -47.114186 | -2.384106 | -43.736190 | -55.759428 |
996 | 2002-09-23 | -47.909157 | -2.196346 | -43.260616 | -54.962861 |
997 | 2002-09-24 | -46.155662 | -2.505858 | -43.390343 | -56.444827 |
998 | 2002-09-25 | -44.870207 | -2.818082 | -41.770450 | -56.236028 |
999 | 2002-09-26 | -45.756302 | -1.328592 | -41.348363 | -55.779009 |
1000 rows × 5 columns
Если пытаетесь выполнить операцию, то можете увидеть исключение, например:
if pd.Series([False, True, False]):
print("I was true")
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-117-5c782b38cd2f> in <module> ----> 1 if pd.Series([False, True, False]): 2 print("I was true") ~/anaconda3/lib/python3.8/site-packages/pandas/core/generic.py in __nonzero__(self) 1327 1328 def __nonzero__(self): -> 1329 raise ValueError( 1330 f"The truth value of a {type(self).__name__} is ambiguous. " 1331 "Use a.empty, a.bool(), a.item(), a.any() or a.all()." ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
Для объяснения см. "Сравнения".
См. также "Подсказки".