import pandas as pdimport scipy.stats as statsurl ="https://raw.githubusercontent.com/nkmwicz/data-for-students/refs/heads/main/soccer-players.csv"df = pd.read_csv(url)df.head()
player_id
first_name
last_name
name
last_season
current_club_id
player_code
country_of_birth
city_of_birth
country_of_citizenship
...
foot
height_in_cm
contract_expiration_date
agent_name
image_url
url
current_club_domestic_competition_id
current_club_name
market_value_in_eur
highest_market_value_in_eur
0
10
Miroslav
Klose
Miroslav Klose
2015
398
miroslav-klose
Poland
Opole
Germany
...
right
184.0
NaN
ASBW Sport Marketing
https://img.a.transfermarkt.technology/portrai...
https://www.transfermarkt.co.uk/miroslav-klose...
IT1
Società Sportiva Lazio S.p.A.
1000000.0
30000000.0
1
26
Roman
Weidenfeller
Roman Weidenfeller
2017
16
roman-weidenfeller
Germany
Diez
Germany
...
left
190.0
NaN
Neubauer 13 GmbH
https://img.a.transfermarkt.technology/portrai...
https://www.transfermarkt.co.uk/roman-weidenfe...
L1
Borussia Dortmund
750000.0
8000000.0
2
65
Dimitar
Berbatov
Dimitar Berbatov
2015
1091
dimitar-berbatov
Bulgaria
Blagoevgrad
Bulgaria
...
NaN
NaN
NaN
CSKA-AS-23 Ltd.
https://img.a.transfermarkt.technology/portrai...
https://www.transfermarkt.co.uk/dimitar-berbat...
GR1
Panthessalonikios Athlitikos Omilos Konstantin...
1000000.0
34500000.0
3
77
NaN
Lúcio
Lúcio
2012
506
lucio
Brazil
Brasília
Brazil
...
NaN
NaN
NaN
NaN
https://img.a.transfermarkt.technology/portrai...
https://www.transfermarkt.co.uk/lucio/profil/s...
IT1
Juventus Football Club
200000.0
24500000.0
4
80
Tom
Starke
Tom Starke
2017
27
tom-starke
East Germany (GDR)
Freital
Germany
...
right
194.0
NaN
IFM
https://img.a.transfermarkt.technology/portrai...
https://www.transfermarkt.co.uk/tom-starke/pro...
L1
FC Bayern München
100000.0
3000000.0
5 rows × 23 columns
Let’s evaluate the various categories.
for col in df.columns:print(f'{col}: {df[col].isna().sum()}')if pd.api.types.is_numeric_dtype(df[col]):print(f'\t mean ({df[col].mean()}), std ({df[col].std()})')else:print(f'\t{col}: {df[col].nunique()}')
The f-stat is 3.21, which is higher than the critical f, which is 2.37. This information tells us that there is a deviation in the mean between positions. Unfortunately, the ANOVA does not tell us what direction that it is in. In order to know where the deviation in mean is, we must run a loop over the positions and run a t-test against every other position.
The output indicates that Attackers are the only position that has a statistically significant difference in birth month are the attackers. For each one of them, the attackers have a positive t-stat, which means that the first groups mean is greater than the second groups mean. In other words, attackers are on the whole born later in the year than (closer to December) than the rest of the positions.