Функции для элементов
Библиотека 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





