Группировка футболистов

Возьмем по 5 футболистов трех различных национальностей, а затем посчитаем средний возраст внутри каждой из национальностей.

Мы видим, что средний возраст приблизительно одинаков между всеми тремя группами.

import pandas as pd

url = "https://raw.githubusercontent.com/dm-fedorov/pandas_basic/master/data/football.csv"

football = pd.read_csv(url)
football.head()
Unnamed: 0 Name Age Nationality Club Value Wage Position Crossing Finishing ... Penalties Composure Marking StandingTackle SlidingTackle GKDiving GKHandling GKKicking GKPositioning GKReflexes
0 0 L. Messi 31 Argentina FC Barcelona 110500000 565000 RF 84 95 ... 75 96 33 28 26 6 11 15 14 8
1 1 Cristiano Ronaldo 33 Portugal Juventus 77000000 405000 ST 84 94 ... 85 95 28 31 23 7 11 15 14 11
2 2 Neymar Jr 26 Brazil Paris Saint-Germain 118500000 290000 LW 79 87 ... 81 94 27 24 33 9 9 15 15 11
3 3 De Gea 27 Spain Manchester United 72000000 260000 GK 17 13 ... 40 68 15 21 13 90 85 87 88 94
4 4 K. De Bruyne 27 Belgium Manchester City 102000000 355000 RCM 93 82 ... 79 88 68 58 51 15 13 5 10 13

5 rows × 42 columns

small_football = football[football.columns[1:8]].head(25)
small_football
Name Age Nationality Club Value Wage Position
0 L. Messi 31 Argentina FC Barcelona 110500000 565000 RF
1 Cristiano Ronaldo 33 Portugal Juventus 77000000 405000 ST
2 Neymar Jr 26 Brazil Paris Saint-Germain 118500000 290000 LW
3 De Gea 27 Spain Manchester United 72000000 260000 GK
4 K. De Bruyne 27 Belgium Manchester City 102000000 355000 RCM
5 E. Hazard 27 Belgium Chelsea 93000000 340000 LF
6 L. Modrić 32 Croatia Real Madrid 67000000 420000 RCM
7 L. Suárez 31 Uruguay FC Barcelona 80000000 455000 RS
8 Sergio Ramos 32 Spain Real Madrid 51000000 380000 RCB
9 J. Oblak 25 Slovenia Atlético Madrid 68000000 94000 GK
10 R. Lewandowski 29 Poland FC Bayern München 77000000 205000 ST
11 T. Kroos 28 Germany Real Madrid 76500000 355000 LCM
12 D. Godín 32 Uruguay Atlético Madrid 44000000 125000 CB
13 David Silva 32 Spain Manchester City 60000000 285000 LCM
14 N. Kanté 27 France Chelsea 63000000 225000 LDM
15 P. Dybala 24 Argentina Juventus 89000000 205000 LF
16 H. Kane 24 England Tottenham Hotspur 83500000 205000 ST
17 A. Griezmann 27 France Atlético Madrid 78000000 145000 CAM
18 M. ter Stegen 26 Germany FC Barcelona 58000000 240000 GK
19 T. Courtois 26 Belgium Real Madrid 53500000 240000 GK
20 Sergio Busquets 29 Spain FC Barcelona 51500000 315000 CDM
21 E. Cavani 31 Uruguay Paris Saint-Germain 60000000 200000 LS
22 M. Neuer 32 Germany FC Bayern München 38000000 130000 GK
23 S. Agüero 30 Argentina Manchester City 64500000 300000 ST
24 G. Chiellini 33 Italy Juventus 27000000 215000 LCB

Предположим, что перед нами стоит задача быстро оценить, сколько футболистов относится к каждой из представленных национальностей.

Так как каждая строка датафрейма содержит информацию об отдельно взятом футболисте, то достаточно посчитать, сколько раз каждая из национальностей встречается в столбце (в серии) Nationality:

s = small_football['Nationality'].value_counts()
s
Nationality
Spain        4
Argentina    3
Belgium      3
Uruguay      3
Germany      3
France       2
Portugal     1
Brazil       1
Croatia      1
Slovenia     1
Poland       1
England      1
Italy        1
Name: count, dtype: int64

Таким образом, функция value_counts подсчитывает для каждого значения в серии количество раз, которое это значение встречается.

Индекс серии s — это уникальные значения, встречающиеся в исходной серии small_df['Nationality']:

s.index
Index(['Spain', 'Argentina', 'Belgium', 'Uruguay', 'Germany', 'France',
       'Portugal', 'Brazil', 'Croatia', 'Slovenia', 'Poland', 'England',
       'Italy'],
      dtype='object', name='Nationality')

Обратите внимание, что в индексе названия сборных идут так же, как в серии, то есть по убыванию числа футболистов. Значит, вызвав первый элемент индекса, мы получим название сборной, у которой больше всего футболистов в рамках датафрейма:

s.index[0]
'Spain'

Если вызовем функцию len для серии s, то получим количество уникальных значений исходной серии, то есть количество национальностей, которые встречаются в датафрейме small_football:

len(s.index)
13

Если хотим определить количество футболистов в small_football, которые относятся к определенной национальности, то достаточно обратиться по нужному индексу к элементу серии:

s['Germany']
3

Получившуюся серию s можно отфильтровать по определенному значению. Например, оставить только такие сборные, в которых больше 1 футболиста:

s.loc[s > 1]
Nationality
Spain        4
Argentina    3
Belgium      3
Uruguay      3
Germany      3
France       2
Name: count, dtype: int64

Сколько футбольных клубов представлено в датасете?

Как называется футбольный клуб, представленный наименьшим количеством игроков в датасете?

Можно посчитать количество футболистов не в абсолютных числах, а в процентах от общего числа в датасете. Для этого надо вызвать функцию value_counts() с параметром normalize=True:

s = small_football['Nationality'].value_counts(normalize=True)
s
Nationality
Spain        0.16
Argentina    0.12
Belgium      0.12
Uruguay      0.12
Germany      0.12
France       0.08
Portugal     0.04
Brazil       0.04
Croatia      0.04
Slovenia     0.04
Poland       0.04
England      0.04
Italy        0.04
Name: proportion, dtype: float64

Таким образом, мы можем быстро определить характеристики распределения футболистов между национальностями в нашем наборе данных. Например, мы узнали, что испанцы составляют 16% от общего числа футболистов, которые были взяты нами для выборки small_football.

Данные об игроках каких позиций (Position) занимают более 10% датасета?

Данные об игроках каких позиций (Position) занимают менее 1% датасета?

Ещё один параметр, который можно передать в функцию value_counts, — это параметр bins. Этот параметр удобно передавать, когда мы хотим сгруппировать данные не по категориальному признаку (каким, например, является национальность), а по численному признаку (например, по возрасту).

Сначала сгруппируем данные по численному признаку без параметра bins:

s = small_football['Age'].value_counts()
s
Age
27    5
32    5
31    3
26    3
33    2
29    2
24    2
25    1
28    1
30    1
Name: count, dtype: int64

Как видно, мы просто сгруппировали футболистов по возрасту и посчитали количество футболистов внутри каждой возрастной группы. Разброс возрастов не слишком большой, поэтому воспринимается эта информация достаточно легко. Например, мы узнали, что больше всего футболистов в двух группах: 27 лет и 32 года.

Другая ситуация складывается, когда мы попытаемся сгруппировать футболистов по их заработной плате:

s = small_football['Wage'].value_counts()
s
Wage
205000    3
355000    2
240000    2
125000    1
300000    1
130000    1
200000    1
315000    1
145000    1
225000    1
285000    1
565000    1
405000    1
94000     1
380000    1
455000    1
420000    1
340000    1
260000    1
290000    1
215000    1
Name: count, dtype: int64

Из-за того, что цифры зарплат повторяются не часто , трудно сделать какие-то выводы. Но всё будет более наглядно, если мы разобьем весь возможный диапазон зарплат на 4 равных промежутка и подсчитаем количество футболистов, попадающих в каждый из промежутков. Именно для этого нужен параметр bins:

s = small_football['Wage'].value_counts(bins=4)
s
(211750.0, 329500.0]     9
(93528.999, 211750.0]    8
(329500.0, 447250.0]     6
(447250.0, 565000.0]     2
Name: count, dtype: int64

Теперь видно, что распределение неравномерное и только 2 футболиста из 25 получают сверхвысокую зарплату.

Давайте посмотрим, что это за футболисты:

small_football.loc[(small_football['Wage'] > s.index[3].left) &
                   (small_football['Wage'] <= s.index[3].right)]
Name Age Nationality Club Value Wage Position
0 L. Messi 31 Argentina FC Barcelona 110500000 565000 RF
7 L. Suárez 31 Uruguay FC Barcelona 80000000 455000 RS

Попробуйте самостоятельно разобраться в том, как работает приведенный выше код, поэтапно вызвав несколько команд и наблюдая за результатом вывода:

small_football = football[football.columns[0:7]].head(25)
s = small_football['Wage'].value_counts(bins=4)
s
(211750.0, 329500.0]     9
(93528.999, 211750.0]    8
(329500.0, 447250.0]     6
(447250.0, 565000.0]     2
Name: count, dtype: int64
s.index
IntervalIndex([ (211750.0, 329500.0], (93528.999, 211750.0],
                (329500.0, 447250.0],  (447250.0, 565000.0]],
              dtype='interval[float64, right]')
s.index[3]
Interval(447250.0, 565000.0, closed='right')
s.index[3].left
447250.0
s.index[3].right
565000.0
small_football['Wage'] > s.index[3].left
0      True
1     False
2     False
3     False
4     False
5     False
6     False
7      True
8     False
9     False
10    False
11    False
12    False
13    False
14    False
15    False
16    False
17    False
18    False
19    False
20    False
21    False
22    False
23    False
24    False
Name: Wage, dtype: bool

В каких пределах находятся худшие 20% показателей точности ударов ногой (FKAccuracy)?

# code

Какие показатели точности ударов ногой демонстрирует большинство футболистов?

# code

В одном из предыдущих примеров мы подсчитывали количество уникальных национальностей с помощью следующего кода:

s = small_football['Nationality'].value_counts()
s.index
Index(['Spain', 'Argentina', 'Belgium', 'Uruguay', 'Germany', 'France',
       'Portugal', 'Brazil', 'Croatia', 'Slovenia', 'Poland', 'England',
       'Italy'],
      dtype='object', name='Nationality')
len(s.index)
13

s.index в данном случае выводит количество уникальных значений, а len(s.index) подсчитывает количество этих значений. На самом деле, сделать это можно было проще, при помощи функции unique:

small_football['Nationality'].unique()
array(['Argentina', 'Portugal', 'Brazil', 'Spain', 'Belgium', 'Croatia',
       'Uruguay', 'Slovenia', 'Poland', 'Germany', 'France', 'England',
       'Italy'], dtype=object)

Функция unique возвращает список уникальных элементов из серии.

Передав получившийся список в функцию len, мы можем подсчитать количество уникальных значений в серии:

len(small_football['Nationality'].unique())
13

Но если наша конечная цель - получить количество уникальных значений в серии, то мы можем поступить ещё проще, вызвав функцию nunique:

small_football['Nationality'].nunique()
13

Иногда бывает полезно преобразовать серию, получившуюся в результате работы функции value_counts, в датафрейм. Для этого нужно к получившейся серии применить функцию reset_index. Эта операция может пригодиться вам в ходе дальнейшего решения задач.

s = small_football['Nationality'].value_counts()
s_df = s.reset_index()
s_df
Nationality count
0 Spain 4
1 Argentina 3
2 Belgium 3
3 Uruguay 3
4 Germany 3
5 France 2
6 Portugal 1
7 Brazil 1
8 Croatia 1
9 Slovenia 1
10 Poland 1
11 England 1
12 Italy 1

Ну и чтобы всё выглядело красиво и правильно, переименуем столбцы получившегося датафрейма в соответствии с тем, что в них хранится:

s_df.columns = ['Nationality','Players Count']
s_df
Nationality Players Count
0 Spain 4
1 Argentina 3
2 Belgium 3
3 Uruguay 3
4 Germany 3
5 France 2
6 Portugal 1
7 Brazil 1
8 Croatia 1
9 Slovenia 1
10 Poland 1
11 England 1
12 Italy 1

Задача 1

У какого процента испанских специалистов (Nationality = 'Spain') зарплата (Wage) находится в пределах 25% минимума от наблюдаемого уровня зарплат? Ответ в виде целого числа (округлите полученный результат) без знака %.

Подсказка: Для решения задачи используйте value_counts() с параметром bins = 4.

# code

Задача 2

Укажите количество уникальных сборных (Nationality), к которым относятся футболисты, выступающие за клуб (Club) "Manchester United".

# code

Задача 3

С помощью функции unique определите двух футболистов из Бразилии (Nationality = 'Brazil'), выступающих за клуб (Club) 'Juventus'. Перечислите их имена (Name, как в датафрейме) через запятую в алфавитном порядке.

# code

Задача 4

Укажите, какой из клубов (Club) насчитывает большее количество футболистов возрастом (Age) старше 35 лет.

# code

Задача 5

С помощью функции value_counts с параметром bins разбейте всех футболистов сборной (Nationality) Аргентины ('Argentina') на 4 равные группы. Укажите, сколько футболистов в возрасте от 34.75 до 41 года в сборной Аргентины.

# code

Задача 6

Сколько процентов футболистов из Испании (Nationality = 'Spain') имеют возраст (Age) 21 год? Введите с точностью до 2 знаков после запятой без указания знака % (например, 12.35).

# code