It's been some time since my last post on football. And we're talking about european soccer here.

So I finally managed to write some functions which allow me to extract player stats from www.transfermarkt.de. The site tracks lots of stats in the world of soccer. For each player, there is information about the dominant foot, height, age, the estimated market value of the player and a load more.

I extracted stats for all registered players from the five major national championships in Europe. Namely, the Bundesliga (Germany), Ligue 1 (France), Premier League (UK), Primera División (Spain) and the Serie A (Italy). Now I have information for 2628 players concerning position, dominant foot, age, height and estimated market value.

The information is in a dataframe called "eu.players".

So let's see if the age of a player predicts its market value and if so, in which way.

The first step is a simple linear regression model. We predict the value of a player (in million Euros) by his age:

> age.val.mod <- lm(val.mill ~ age, data = eu.players)
> anova(age.val.mod)

Analysis of Variance Table

Response: val.mill
            Df Sum Sq Mean Sq F value Pr(>F)
age          1     61  60.836  1.1445 0.2848
Residuals 2619 139209  53.153

That's a little bit disappointing. According to the linear model, there is no significant relation between the age and the value of a player. Let's plot this relation.
(click to enlarge)

This plot strongly suggests another regression model. But it seems as if we need to include a non-linear term. Maybe, players get more valuable over time but then lose value again.

> age.val.mod2 <- lm(val.mill ~ age + I(age^2), data = eu.players)
> anova(age.val.mod2)
Analysis of Variance Table

Response: val.mill
            Df Sum Sq Mean Sq  F value Pr(>F)    
age          1     61    60.8   1.1979 0.2738    
I(age^2)     1   6248  6248.5 123.0332 <2e-16 ***
Residuals 2618 132960    50.8                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 


> anova(age.val.mod2, age.val.mod3)
Analysis of Variance Table

Model 1: val.mill ~ age + I(age^2)
Model 2: val.mill ~ age + I(age^2) + I(age^3)
  Res.Df    RSS Df Sum of Sq     F   Pr(>F)   
1   2618 132960                               
2   2617 132459  1    501.54 9.909 0.001663 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 

The quadratic term for age is highly significant. Also, the model comparison done by anova(<model1>, <model2>) shows that the inclusion of the quadratic term improves our model.

Now, let's plot this relationship again, including model estimates for the quadratic term. Also, we use limits for the y-axis because Lionel Messi has an estimated worth of 120 million Euros and this "crushes" the majority of the players down to the x-axis.

(click to enlarge)

We get a quite clear result: The relationship between age and value of a football player seems to be a quadratic one. The "golden age" is 26 years. We can extract this value from the predicted values of model age.val.mod2:
> df <- data.frame(age = sort(unique(eu.players$age))) 
> df$age[which.max(predict(age.val.mod2, newdata = df))]
[1] 26

Obviously, there's a lot more one can do with the kind of data we have. But this has to wait for some other time. I'll start with a teaser: Let's see if there are some clear relationships between "footedness" (dominant foot) and position...

(click to enlarge)

This mosaic plot and the Standardized Residuals obtained from a Chi-Square test suggest that there are more players with a dominant left foot in defense than would be expected if footedness is distributed equally over the different positions. Also, players with no real dominant foot ("both") are overrepresented in midfield and forward positions. This should give them the opportunity for a more flexible style of play - a competence mostly needed in forward positions.

More insights from this dataset coming soon...





0

Add a comment

Hi all, this is just an announcement.

I am moving Rcrastinate to a blogdown-based solution and am therefore leaving blogger.com. If you're interested in the new setup and how you could do the same yourself, please check out the all shiny and new Rcrastinate over at

http://rcrastinate.rbind.io/

In my first post over there, I am giving a short summary on how I started the whole thing. I hope that the new Rcrastinate is also integrated into R-bloggers soon.

Thanks for being here, see you over there.

Alright, seems like this is developing into a blog where I am increasingly investigating my own music listening habits.

Recently, I've come across the analyzelastfm package by Sebastian Wolf. I used it to download my complete listening history from Last.FM for the last ten years. That's a complete dataset from 2009 to 2018 with exactly 65,356 "scrobbles" (which is the word Last.FM uses to describe one instance of a playback of a song).
3

Giddy up, giddy it up

Wanna move into a fool's gold room

With my pulse on the animal jewels

Of the rules that you choose to use to get loose

With the luminous moves

Bored of these limits, let me get, let me get it like

Wow!

When it comes to surreal lyrics and videos, I'm always thinking of Beck. Above, I cited the beginning of the song "Wow" from his latest album "Colors" which has received rather mixed reviews. In this post, I want to show you what I have done with Spotify's API.

Click here for the interactive visualization

If you're interested in the visualisation of networks or graphs, you might've heard of the great package "visNetwork". I think it's a really great package and I love playing around with it. The scenarios of graph-based analyses are many and diverse: whenever you can describe your data in terms of "outgoing" and "receiving" entities, a graph-based analysis and/or visualisation is possible.
12

Here is some updated R code from my previous post. It doesn't throw any warnings when importing tracks with and without heart rate information. Also, it is easier to distinguish types of tracks now (e.g., when you want to plot runs and rides separately). Another thing I changed: You get very basic information on the track when you click on it (currently the name of the track and the total length).

Have fun and leave a comment if you have any questions.
3

So, Strava's heatmap made quite a stir the last few weeks. I decided to give it a try myself. I wanted to create some kind of "personal heatmap" of my runs, using Strava's API. Also, combining the data with Leaflet maps allows us to make use of the beautiful map tiles supported by Leaflet and to zoom and move the maps around - with the runs on it, of course.

So, let's get started. First, you will need an access token for Strava's API.

I've been using the ggplot2 package a lot recently. When creating a legend or tick marks on the axes, ggplot2 uses the levels of a character or factor vector. Most of the time, I am working with coded variables that use some abbreviation of the "true" meaning (e.g. "f" for female and "m" for male or single characters for some single character for a location: "S" for Stuttgart and "M" for Mannheim).

In my plots, I don't want these codes but the full name of the level.

It's been a while since I had the opportunity to post something on music. Let's get back to that.

I got my hands on some song lyrics by a range of artists. (I have an R script to download all lyrics for a given artist from a lyrics website.
4

Lately, I got the chance to play around with Shiny and Leaflet a lot - and it is really fun! So I decided to catch up on an old post of mine and build a Shiny application where you can upload your own GPX files and plot them directly in the browser.

Of course, you will need some GPX file to try it out. You can get an example file here (you gonna need to save it in a .gpx file with a text editor, though). Also, the Shiny application will always plot the first track saved in a GPX file.
9
Blog Archive
BlogRoll
BlogRoll
  • Announcing rixpress As I’ve already discussed in this vignette of my {rix} package, it is very easy to run a {targets} pipeline inside of a Nix environment for increased re...

    1 day ago
Loading
Dynamic Views theme. Powered by Blogger. Report Abuse.