The use of bicycles in Helsinki

Every six months, the city of Helsinki publishes data on the number of cyclists in Helsinki per hour. Since 2014, a number of meters have been planted in different areas of Helsinki (Kaisaniemi, Munkkiniemi 1 and 2, Hesperian, Eteläesplanadi and Baana) to count the number of bikes. The latest data is freely available here.

I amalgamated this data set with data on the weather in Helsinki for each day to plot some graphics and create some analysis on the factors that determine the use of bicycles in Helsinki.

1. Data visualization

I found some very good models for the data visualization on Kaggle that I mostly use here.

fig1

The figure 1 shows the average number of bikes used in Helsinki per hour based on the day. Most of the cyclists seem to use the bike on weekdays to commute. We see two peaks in use, one at 8 in the morning and the second at 4pm.
It is noticeable that the motivation to ride a bike to go to work significantly decreases during the week. Therefore, there is approximatively 40% less bikes used on Friday at 8h than on Tuesday at the same time.
On Saturday and Sunday, people use bicycles in the afternoon but we don’t see the same level of use than on a weekday.

fig2

The figure 2 displays the number of bikes per day from 2014 to March 2017 and by temperature. We see a similar trend in the use of bikes in the different years. To no surprise, the maximum number of cyclists per day (more than 20 000 per day) is higher during the summer when the temperatures are high whereas when the temperature is lower than 0, the number of cyclists is usually lower (less than 10 000 a day).

fig3

Figure 3 shows the average number of bikes per day by month. The number of bicycles is significant in May 2016 compared to the other years. This might be partly explained by the introduction of a bicycle-sharing system in the city centre of Helsinki in spring 2016. Therefore, it might encourage people living in Helsinki but also tourists to use these bikes.

2. Insights on the factors that determine the use of bicycles

fig4

The correlation matrix shows the positive (blue) and negative (red) correlations between the number of bikes used (variable total4) and weather variables such as the temperature (variable temp), the morning dew (variable rosee), the humidity (humid), the atmospheric pressure (press), the visibility (visi), the wind (wind) and the accumulated precipitations (preci) on a day (preci).

The number of cyclists per day is highly and positively correlated with the temperature and the morning dew. In other words, when the temperature is high, people use more bicycles. On the other hand, humidity is highly and negatively correlated with the number of cyclist. The accumulated precipitations and the wind are not significantly correlated.

Analyse des tweets du débat d’entre-deux-tours

Emmanuel Macron et Marine Le Pen se sont affrontés lors du débat de l’entre-deux-tours mercredi dernier. Ce débat télévisé suivi par près de 16 millions de téléspectateurs a été l’occasion pour moi de tester le package « TwitteR » qui permet de récupérer les tweets.

Je me suis concentré sur les tweets publiés pendant le débat de 21h à 23h30 et mentionnant l’un ou l’autre des comptes officiels twitter des candidats (@EmmanuelMacron pour Emmanuel Macron et @MLP_officiel).

1. Petit tutoriel pour récupérer les tweets avec TwitteR

Le package TwitteR de R permet de récupérer les tweets et de les mettre sous forme de table de données (data frame). Cette forme est particulièrement utile pour réaliser des analyses de ces données comme par exemple les analyses de sentiments à partir des tweets.

Il est très facile de récupérer des tweets en utilisant l’API de Twitter. Je présente ici les étapes que j’ai suivies.

1 – Pour ceux qui n’en possèdent pas, il faut dans un premier temps créer un compte twitter ici.

2 – La deuxième étape consiste à s’enregistrer sur la partie développeurs « Twitter Apps » avec l’identifiant et le mot de passe du compte nouvellement créé.

3 – Une fois enregistré sur la partie Apps, il faut créer une « application » et remplir les champs suivants : name, description, website et callback URL. Le nom, la description et le site internet n’ont pas réellement d’importance. Si vous n’avez pas de site internet, vous pouvez juste entrer le nom de ce blog : http://dataworld.blog Pour le CallBack URL, écrivez sans les guillemets http://127.0.0.1:1410. Acceptez l’accord de licence puis cliquez sur créer l’application.

SC1

4 – En vous connectant sur la partie Apps vous pourrez accéder à votre nouvelle « application ». Dans l’onglet « Keys and Access Tokens », vous aurez accès à votre Consumer Key, Consumer Secret et également un peu plus bas sur la même page l’Access Token et l’Access Token Secret.

SC2

 

5 – Dans RStudio, lancez les quelques lignes suivantes :

 

# Installer et lancer le package TwitteR
install.packages("twitteR")
library(twitteR)

# Connexion avec setup twitter
consumer_key <- "votre_consumer_key"
consumer_secret <- "votre_consumer_secret"
access_token <- "votre_access_token"
access_secret <- "votre_access_secret"
setup_twitter_oauth(consumer_key,
consumer_secret,
access_token,
access_secret)

6 – Récupérer 50 tweets mentionnant le compte officiel d’Emmanuel Macron et les mettre sous forme de data frame :

list_macron <- searchTwitter("@EmmanuelMacron", n = 50)
df_macron <- twListToDF(list_macron) 

Les 50 derniers tweets mentionnant Emmanuel Macron sont récupérés. En plus du tweet sous forme de texte, de nombreuses informations sont extraites, comme par exemple : la date de création du tweet, l’identifiant du tweet, le nombre de retweet, la source (iphone ou android) parfois la latitude et longitude, tweet favori etc…

Il est à noter que le nombre de tweet maximum qu’il est possible d’extraire avec une connexion est de n = 3000. De même, il y a une limite au nombre de connections à l’API de Twitter. De ce fait, cela a limité le nombre de tweets que j’ai pu récupérer durant la soirée de débat.

Pour pallier cette limite, j’ai appris après coup qu’il existe le package StreamR qui permet de laisser la connexion ouverte et donc de récupérer tous les tweets pendant toute la durée d’ouverture de la connexion

2. Le nombre de tweets par minute pour chaque candidat

Comme expliqué précédemment, la limite imposée de 3000 tweet par connexion ne m’a pas permis d’extraire en continu la totalité des tweets publiés pendant la soirée électorale. Il y a donc certaines plages horaires où aucun tweet n’a été récupéré (voir les deux graphiques suivants). Durant la soirée de débat 85197 tweets ont été récupéré mentionnant Marine Le Pen et 81546 mentionnant Emmanuel Macron. On constate des tendances similaires pour les deux candidats : le nombre de tweet par minute est au maximum en fin d’émission avec près de 1500 tweets par minute récupéré.

Pour afficher le nombre de tweet par minute, j’ai utilisé le code suivant pour les tweets d’Emmanuel Macron (le code est identique pour ceux mentionnant Marine Le Pen).

# Mettre la date de création du tweet sous forme POSIXct
df_macron$date <- format(df_macron$created, format="%Y-%m-%d")
df_macron$date <- as.POSIXct(df_macron$date)

# Histogramme du nombre de tweet par minute
# En changeant binwidth, il est possible de modifier la largeur de l’intervalle, ici 1 minute.
library(ggplot2)
minutes <- 60
ggplot(data=df_macron, aes(x=date)) +
geom_histogram(aes(fill=..count..),binwidth= 1*minutes) +
scale_x_datetime("Heure") +
scale_y_continuous("Nombre de tweets") 

 

macron_fig1.1.png
Nombre de tweets par minute mentionnant Emmanuel Macron

 

lepen_fig1.2.png
Nombre de tweets par minute mentionnant Marine Le Pen

3. Les mots les plus fréquemment utilisés dans les tweets

En exploitant les plus de 80 000 tweets publiés pour chaque candidat, il est possible de construire des nuages de mots (wordcloud) en utilisant le package wordcloud.

Le code utilisé est le suivant :

# Mettre sous forme exploitable les tweets
df_macron$text <- gsub(","," ",df_macron$text) # Enlever les virgules
df_macron$text <- gsub("'"," ",df_macron$text) # Enlever les apostrophes
df_macron$text = gsub("(RT|via)((?:\\b\\W*@\\w+)+)", "", df_macron$text) # Enlever les mentions de retweet
df_macron$text = gsub("@\\w+", "", df_macron$text) # Enlever les @pseudo
df_macron$text <- gsub("http[^[:space:]]*", "", df_macron$text) # Enlever les liens
df_macron$text <- gsub("[^[:alpha:][:space:]]*", "", df_macron$text) # Enlever les nombres et la ponctuation
df_macron$text <- gsub("[ ]{2,}", " ", df_macron$text) # Enlever les espaces multiples
df_macron$text <- gsub("^\\s+|\\s+$", "", df_macron$text) # Enlever les espaces non-nécessaires

# Mettre le texte sous forme minuscule
tryToLower <- function(x){
y = NA
try_error = tryCatch(tolower(x), error = function(e) e)
if (!inherits(try_error, 'error'))
y = tolower(x)
return(y)
}
text_macron <- sapply(df_macron$text, tryToLower)

# Enlever les “mots vides” (exemple : le, la, du, etc…) + les noms des candidats
library(tm)
text_macron <- removeWords(text_macron,
c(stopwords("french"), stopwords("english"),
"est", “marine“, “le pen“, “emmanuel“, “debat“))

# Mettre les mots sous formes de tableau de données et enlever tous les mots qui n’apparaissent pas au moins dans 1% des tweets (sparsity = 0.99)
corpus_macron <- Corpus(VectorSource(text_macron))
dtm_macron <- DocumentTermMatrix(corpus_macron)
dtms_macron <- removeSparseTerms(dtm_macron, 0.99)
sparseData_macron <- as.data.frame(as.matrix(dtms_macron))
colnames(dtms_macron) <- make.names(colnames(dtms_macron))

# Construction du nuage de mots (wordcloud)
library(wordcloud)
wordcloud(colnames(sparseData_macron), colSums(sparseData_macron),
scale=c(2, 0.5), random.color=FALSE,
colors = c("#6BAED6", "#4292C6", "#2171B5", "#08519C", "#08306B"),
rot.per = 0.3)  # pourcentage de mots écrits à la verticale

 

macron
Wordcloud Emmanuel Macron
lepen.png
Wordcloud Marine Le Pen

 

macron_fig2.1

lepenfig2.2.png

4. Les plus gros twittos de la soirée

Sans grande surprise, le compte « patriote libre » a le plus twitté avec plus de 100 tweets (ou retweets) durant le débat côté Marine Le Pen et « En marche Paris 7 » a quant à lui envoyé plus de 150 tweets.

tweet macron.png

tweetlepen

Elections présidentielles en France : l’abstention, la clé du résultat ?

Le deuxième tour de l’élection présidentielle en France aura lieu ce dimanche. Comme annoncé par les instituts de sondage depuis plusieurs semaines, Emmanuel Macron et Marine Le Pen sont arrivés en tête lors du premier tour avec respectivement 24% et 21,3% des suffrages exprimés.

Emmanuel Macron fait figure de grand favori, les estimations tablent sur son élection à environ 60% des voix contre 40% pour Marine Le Pen. Alors que les appels à soutenir Emmanuel Macron se sont multipliés de part et d’autre de l’échiquier politique, Jean-Luc Mélenchon – quatrième homme de cette présidentielle avec 19,6% des voix – a surpris en n’appelant pas à voter pour le candidat du mouvement « En Marche », tout en réitérant sa volonté de combattre l’extrême droite de Marine Le Pen.

Le résultat du second tour de l’élection devrait donc fortement dépendre du report des voix des 7 millions d’insoumis qui ont soutenu Jean-Luc Mélenchon au premier tour.

En me basant sur le sondage BVA pour la Voix du Nord qui estime les reports de voix pour chaque candidat, je me suis amusé à regarder quel pouvait être l’effet d’une abstention/vote blanc /vote nul des électeurs de Jean-Luc Mélenchon sur le résultat de l’élection. Je précise que ce petit calcul de coin de table n’a aucune valeur scientifique.

En plus des hypothèses de BVA sur les reports de voix, j’ai rajouté les hypothèses suivantes :

  • Le report pour Macron des électeurs ayant voté Macron au premier tour est de 100% et le report pour Le Pen des électeurs ayant voté Le Pen au premier tour est de 100% également. Cette hypothèse est peu réaliste mais elle ne devrait pas affecter significativement le résultat. S’il existe des reports de voix entre Macron et Le Pen et entre Le Pen et Macron, il est raisonnable de penser qu’ils sont grosso modo du même ordre de  grandeur et donc qu’ils s’annulent.
  • J’estime à la louche un report des voix pour les « petits candidats » de respectivement de 40% pour Macron 40% pour Le Pen et 20% en abstention.
  • Les votes blancs, nuls et abstention du premier tour sont reportés à 95% vers l’abstention et à 2,5% pour chacun des candidats.

election

Toutes choses égales par ailleurs, pour une abstention, un vote nul ou un vote blanc des électeurs de Mélenchon de 38% (l’hypothèse de BVA), Marine Le Pen devrait obtenir un score d’un peu moins de 42%. Il est à noter que je garde l’hypothèse BVA d’un report des voix des électeurs de Mélenchon pour Le Pen de 18%.

Si l’abstention des électeurs indécis de Mélenchon est plus importante – de l’ordre de 60 à 70% – comme ce que semble suggérer les résultats de la consultation lancée sur la plateforme de la France insoumise, Emmanuel Macron pourrait l’emporter avec un score d’environ 55%.

A simple example of webscraping with R : the top 5% economist ranking

The data analyzed in this post come from RePEc which is a collaborative project well-known by economists. It gathers links to working papers, journal articles or software components and also provides a ranking of more than 30,000 registered economists. This ranking is calculated by taking a harmonic mean of the ranks of many criterion considered such as the number of works, the number of citations, the H-index, the number of followers on twitter, etc… For a complete list of the criteria used, please see : https://ideas.repec.org/top/.

1. Scrap the data

To scrap the data, I used the R package rvest and the useful functions associated with this package: read_html, html_nodes and html_text to get the data for the top 5% economists, top 5% women economists and the top 5% in 2007. More precise information on the package is available here.

For my basic needs, I used the following lines of code to extract the data:

# Install the package and load it
install.packages(“rvest”)
library(rvest)

# Define the URL and download the HTML page with read_html
url1 <- "https://ideas.repec.org/top/top.person.alldetail.html"
page1 <- read_html(url1)

# To extract pieces out of the HTML page as a table format, use html_table
table1 <- html_table(page1)

# To extract pieces of the HTML page using css selectors, use html_nodes
# The following line extract information inside the <a> selector.
name_economist <- html_nodes(page1,"a")

# Extract attributes, text and tag with html_text
name_economist <- html_text(name_economist)

# Create a data frame with data.frame
name_economist <- data.frame(name_economist)

2. Information from the data

There are 2,489 economists in this top 5% ranking, of whom 109 are dead. Women represent only 6.5% of these 2,489 economists.

American universities dominate this ranking with more than 50% of the top ranked economists affiliated with a US university. Harvard University is the first institution in terms of the number of top 5% economists with 33 economists out of the total 2,489.

California is the state/country that gathers the highest number of top economists with 218, followed by the UK with 207 and then the state of Massachusetts with 193.

3. Number of economists per million population

Using the package rworldmap and data on population found on wikipedia, I constructed a map of the number of economists per million population. To have more precise info on how to use the rwolrdmap package, please read the very good introduction that I used here.

# Install and load the package
install.packages(“rworldmap”)
install.packages(“rworldmap”)

# Join the data frame df to a map with the name of the countries.
n1 <- joinCountryData2Map(df, joinCode="NAME", nameJoinColumn="state")

# Create a color palette
op <- palette(c("lavender", "yellow", "orange", "red"))

# Create the vector cutVector to separate the data in 4 categories:
# Countries between the minimum number of economists per million population
# (df$nbr_per_million) and 1; between 1 and 2; between 2 and 3 and between 3 and the max
cutVector <- c(min(df$nbr_per_million),1,2,3, max(df$nbr_per_million))

# Define the categories and name them for the legend
n1@data[["numcategorie"]] <- cut(n1@data[["nbr_per_million"]], cutVector, include.lowest=TRUE)
levels(n3@data[["numcategorie"]]) <- c(">0 and <1", "between 1 and 2","between 2 and 3", "more than 3")

#   Plot the map n1, use the categories defined with categories, the palette previously defined and a legend.
par(mai=c(0,0,0.2,0),xaxs="i",yaxs="i")
mapParams <- mapCountryData(n1, nameColumnToPlot="numcategorie", colourPalette = "palette",
mapTitle="Number of top 5% economist per million population", addLegend = T, missingCountryCol = NA,
catMethod = "categorical", mapRegion = "Eurasia")

# At end of plotting, reset palette to previous settings:
palette(op)

world

europe

We can see that amongst the countries in Europe, the UK, Sweden, Switzerland, Belgium, Netherlands are the countries for which the number of top economists per million population is the highest.

4. Evolution of the ranking

Using the wayback machine, I retrieved data from 2007 to compare with data from 2017. On average, the people who were present in the data for both 2007 and 2017 have lost 131 places in the ranking. The most significant improvement in ranking has been seen in the placement of Martin Feldstein, who gained 1,435 places in 10 years and is now ranked 15.

Top 10 best progression:

tab1.png

Top 10 biggest drop:

tab2.png