Функции для элементов
Библиотека Pandas построена на базе NumPy и расширяет возможности последней, используя их по отношению к новым структурам данных: Series
и Dataframe
. В их числе универсальные функции, называемые ufunc
. Они применяются к элементам структуры данных.
>>> 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 |
Например, можно найти квадратный корень для каждого значения в Dataframe
с помощью функции np.sqrt()
.
>>> np.sqrt(frame)
ball | pen | pencil | paper | |
---|---|---|---|---|
red | 0.000000 | 1.000000 | 1.414214 | 1.732051 |
blue | 2.000000 | 2.236068 | 2.449490 | 2.645751 |
yellow | 2.828427 | 3.000000 | 3.162278 | 3.316625 |
white | 3.464102 | 3.605551 | 3.741657 | 3.872983 |
Функции для строк и колонок
Применение функций не ограничивается универсальными, но включает и те, что были определены пользователем. Важно отметить, что они работают с одномерными массивами, выдавая в качестве результата единое число. Например, можно определить лямбда-функцию, которая вычисляет диапазон значений элементов в массиве.
>>> f = lambda x: x.max() - x.min()
Эту же функцию можно определить и следующим образом:
>>> def f(x):
... return x.max() - x.min()
С помощью apply()
новая функция применяется к Dataframe
.
>>> frame.apply(f)
ball 12
pen 12
pencil 12
paper 12
dtype: int64
В этот раз результатом является одно значение для каждой колонки, но если нужно применить функцию к строкам, а на колонкам, нужно лишь поменять значение параметра axis
и указать 1
.
>>> frame.apply(f, axis=1)
red 3
blue 3
yellow 3
white 3
dtype: int64
Метод apply()
не обязательно вернет скалярную величину. Он может вернуть и объект Series
. Можно также включить и применить несколько функций одновременно. Это делается следующим образом:
>>> def f(x):
... return pd.Series([x.min(), x.max()], index=['min','max'])
После этого функция используется как и в предыдущем примере. Но теперь результатом будет объект Dataframe
, а не Series
, в котором столько строк, сколько значений функция возвращает.
>>> frame.apply(f)
ball | pen | pencil | paper | |
---|---|---|---|---|
min | 0 | 1 | 2 | 3 |
max | 12 | 13 | 14 | 15 |
Статистические функции
Большая часть статистических функций массивов работает и с Dataframe
, поэтому для них не нужно использовать apply()
. Например, sum()
и mean()
могут посчитать сумму или среднее значение соответственно для элементов внутри объекта Dataframe
.
>>> frame.sum()
ball 24
pen 28
pencil 32
paper 36
dtype: int64
>>> frame.mean()
ball 6.0
pen 7.0
pencil 8.0
paper 9.0
dtype: float64
Есть даже функция describe()
, которая позволяет получить всю статистику за раз.
>>> frame.describe()
ball | pen | pencil | paper | |
---|---|---|---|---|
count | 4.000000 | 4.000000 | 4.000000 | 4.000000 |
mean | 6.000000 | 7.000000 | 8.000000 | 9.000000 |
std | 5.163978 | 5.163978 | 5.163978 | 5.163978 |
min | 0.000000 | 1.000000 | 2.000000 | 3.000000 |
25% | 3.000000 | 4.000000 | 5.000000 | 6.000000 |
50% | 6.000000 | 7.000000 | 8.000000 | 9.000000 |
75% | 9.000000 | 10.000000 | 11.000000 | 12.000000 |
max | 12.000000 | 13.000000 | 14.000000 | 15.000000 |
Сортировка и ранжирование
Еще одна операция, использующая индексирование pandas, — сортировка. Сортировка данных нужна часто, поэтому важно иметь возможность выполнять ее легко. Библиотека pandas предоставляет функцию sort_index()
, которая возвращает новый объект, идентичный стартовому, но с отсортированными элементами.
Сначала рассмотрим варианты, как можно сортировать элементы Series
. Операция простая, ведь сортируется всего один список индексов.
>>> ser = pd.Series([5,0,3,8,4],
... index=['red','blue','yellow','white','green'])
>>> ser
red 5
blue 0
yellow 3
white 8
green 4
dtype: int64
>>> ser.sort_index()
blue 0
green 4
red 5
white 8
yellow 3
dtype: int64
В этом примере элементы были отсортированы по алфавиту на основе ярлыков (от A до Z). Это поведение по умолчанию, но достаточно сделать значением параметра ascending
False
и элементы объекта отсортируются иначе.
>>> ser.sort_index(ascending=False)
yellow 3
white 8
red 5
green 4
blue 0
dtype: int64
В случае с Dataframe
можно выполнить сортировку независимо для каждой из осей. Если требуется отсортировать элементы по индексам, то нужно просто использовать sort_index()
как обычно. Если же требуется сортировка по колонкам, то необходимо задать значение 1 для параметра axis
.
>>> 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 |
>>> frame.sort_index()
ball | pen | pencil | paper | |
---|---|---|---|---|
blue | 4 | 5 | 6 | 7 |
red | 0 | 1 | 2 | 3 |
white | 12 | 13 | 14 | 15 |
yellow | 8 | 9 | 10 | 11 |
>>> frame.sort_index(axis=1)
ball | paper | pen | pencil | |
---|---|---|---|---|
red | 0 | 3 | 1 | 2 |
blue | 4 | 7 | 5 | 6 |
yellow | 8 | 11 | 9 | 10 |
white | 12 | 15 | 13 | 14 |
Но это лишь то, что касается сортировки по индексам. Но часто приходится сортировать объект по значениям его элементов. В таком случае сперва нужно определить объект: Series
или Dataframe
.
Для первого подойдет функция sort_values()
.
>>> ser.sort_values()
blue 0
yellow 3
green 4
red 5
white 8
dtype: int64
А для второго — та же функция sort_values()
, но с параметром by
, значением которого должна быть колонка, по которой требуется отсортировать объект.
>>> frame.sort_values(by='pen')
ball | pen | pencil | paper | |
---|---|---|---|---|
red | 0 | 1 | 2 | 3 |
blue | 4 | 5 | 6 | 7 |
yellow | 8 | 9 | 10 | 11 |
white | 12 | 13 | 14 | 15 |
Если сортировка основана на двух или больше колонках, то by
можно присвоить массив с именами колонок.
>>> frame.sort_values(by=['pen','pencil'])
ball | pen | pencil | paper | |
---|---|---|---|---|
red | 0 | 1 | 2 | 3 |
blue | 4 | 5 | 6 | 7 |
yellow | 8 | 9 | 10 | 11 |
white | 12 | 13 | 14 | 15 |
Ранжирование тесно связано с операцией сортировки. Оно состоит из присваивания ранга (то есть, значения, начинающегося с 0 и постепенно увеличивающегося) к каждому элементу Series
. Он присваивается элементам, начиная с самого младшего значения.
>>> ser.rank()
red 4.0
blue 1.0
yellow 2.0
white 5.0
green 3.0
dtype: float64
Ранг может быть присвоен и согласно порядку, в котором элементы содержатся в структуре (без операции сортировки). В таком случае нужно добавить параметр method
со значением first
.
>>> ser.rank(method='first')
red 4.0
blue 1.0
yellow 2.0
white 5.0
green 3.0
dtype: float64
По умолчанию даже ранжирование происходит в возрастающем порядке. Для обратного нужно задать значение False
для параметра ascending
.
>>> ser.rank(ascending=False)
red 2.0
blue 5.0
yellow 4.0
white 1.0
green 3.0
dtype: float64
Корреляция и ковариантность
Два важных типа статистических вычислений — корреляция и вариантность. В pandas они представлены функциями corr()
и cov()
. Для их работы нужны два объекта Series
.
>>> seq2 = pd.Series([3,4,3,4,5,4,3,2],['2006','2007','2008',
'2009','2010','2011','2012','2013'])
>>> seq = pd.Series([1,2,3,4,4,3,2,1],['2006','2007','2008',
'2009','2010','2011','2012','2013'])
>>> seq.corr(seq2)
0.7745966692414835
>>> seq.cov(seq2)
0.8571428571428571
Их же можно применить и по отношению к одному Dataframe
. В таком случае функции вернут соответствующие матрицы в виде двух новых объектов Dataframe
.
>>> frame2 = pd.DataFrame([[1,4,3,6],[4,5,6,1],[3,3,1,5],[4,1,6,4]],
... index=['red','blue','yellow','white'],
... columns=['ball','pen','pencil','paper'])
>>> frame2
ball | pen | pencil | paper | |
---|---|---|---|---|
red | 1 | 4 | 3 | 6 |
blue | 4 | 5 | 6 | 1 |
yellow | 3 | 3 | 1 | 5 |
white | 4 | 1 | 6 | 4 |
>>> frame2.corr()
ball | pen | pencil | paper | |
---|---|---|---|---|
ball | 1.000000 | -0.276026 | 0.577350 | -0.763763 |
pen | -0.276026 | 1.000000 | -0.079682 | -0.361403 |
pencil | 0.577350 | -0.079682 | 1.000000 | -0.692935 |
paper | -0.763763 | -0.361403 | -0.692935 | 1.000000 |
>>> frame2.cov()
ball | pen | pencil | paper | |
---|---|---|---|---|
ball | 2.000000 | -0.666667 | 2.000000 | -2.333333 |
pen | -0.666667 | 2.916667 | -0.333333 | -1.333333 |
pencil | 2.000000 | -0.333333 | 6.000000 | -3.666667 |
paper | -2.333333 | -1.333333 | -3.666667 | 4.666667 |
С помощью метода corwith()
можно вычислить попарные корреляции между колонками и строками объекта Dataframe
и Series
или другим DataFrame()
.
>>> ser = pd.Series([0,1,2,3,9],
... index=['red','blue','yellow','white','green'])
>>> ser
red 0
blue 1
yellow 2
white 3
green 9
dtype: int64
>>> frame2.corrwith(ser)
ball 0.730297
pen -0.831522
pencil 0.210819
paper -0.119523
dtype: float64
>>> frame2.corrwith(frame)
ball 0.730297
pen -0.831522
pencil 0.210819
paper -0.119523
dtype: float64