German Bundestag meets Twitter

A Network Analysis of the Members of the German Bundestag

2020-03-08 | Lukas Tatge

German Bundestag meets Twitter

Investigating German MPs on Twitter

Since Angela Merkel’s famous ‘Neuland’ quote in 2013, the influence and relevance of social media for society, but also for politicians, has greatly increased. Politicians use the Twitter platforms mainly to communicate with the public, the media and with each other. In a fast-moving and attention-driven social media world, I want to use the social network approach to take a look at how elected German politicians are connected to each other and whether the party structure we observe in the real world is also visible in this digital space.

I choose the social network Twitter to perform this analysis because it is often the primary social media platform for politicians to communicate publicly. Also, it offers a good API. In December 2019, I manually collected all the names of Twitter accounts, real life names and party membership based on the official list of politicians who are part of the German Bundestag. Based on this, I build a social network based on which politicians follow each other on Twitter, in order to determine the importance of each politician in that social network.

To collect the necessary information about the following of the individual politician accounts, I use the R package {rtweet}. With the function get_friends() it is possible to get all Twitter accounts that someone is following. An important limitation for this API is that it is only possible to send 15 requests every 15 minutes, so I wrote a function that only sends new requests after 15 minutes. After using this function for every politician, I got a file with two columns and more than 400,000 rows. The first column contains the politicians account, and the second column contains the account ID of another account he is following.

Since the relationship between two politicians can be unilateral or bilateral, I add a third column with the value 1 if the relationship is unilateral, or 2 if the relationship is bilateral. To include party membership, I use my original file on politicians and by using the R package {dplyr}, I then include party membership by merging these two tables. For the visual representation of this social network, I use the program NetGraph, in which I display only the nodes (a Twitter account) of the politicians and use different colors depending on the party membership. The result is shown in the following picture.

The network graph of German MPs on Twitter

The network graph of German MPs on Twitter

In this figure, you first see that each party is well connected internally and has few members who are not close to their fellow party members. A second finding is that the AfD is clearly separated from the other parties. This somehow fits with the public announcement of all large German parties not to cooperate with this radical party. It also shows that SPD, Buendnis 90/Die Gruenen and Die Linke are more closely linked and that CDU/CSU and FDP are also more closely linked. This is in line with previous government coalitions.

In a second step, I then create a non-graphical social network with the R-package {igraph}. There, I create a graph (social network) which is based only on the politician nodes (Twitter accounts) and their relationships (weight of the connection). Then, I calculate the ‘Betweenness’ and the ‘Closeness’, which are both different measures for the importance or centralization of a note in a social network. Betweenness centrality measures the number of times a politician node lies on the shortest path between other politicians.

This measure shows which politicians are ‘bridges’ between other politician in this network and just counts this number. In contrast to this, the Closeness centrality evaluates each politician’s node based on their ‘Closeness’ to all other politicians in the network. This measure calculates the shortest paths between all politicians, then assigns each politician a rating based on its sum of shortest paths. The results are shown in the following table.


1Stefan LiebichDie Linke43065
2Kordula Schulz-AscheB90/Gruene7387
3Frank SchaefflerFDP7343
4Frank PasemannAfD6767
5Dorothee BaerCSU6491
6Andreas NickCDU5904
7Heiko MaasSPD5686
8Johannes KahrsSPD5434
9Konstantin von NotzB90/Gruene4528
10Uwe Kamann-3736


1Frank PasemannAfD0.0016420361
2Uwe Kamann-0.0009832842
3Johannes KahrsSPD0.0009242144
4Frank SchaefflerFDP0.0009107468
5Ulli NissenSPD0.0009025271
6Stefan LiebichDie Linke0.0009017133
7Florian PronoldSPD0.0008888889
8Felix SchreinerCDU0.0008873114
9Edgar Franke-0.0008826125
10Tobias Lindner-0.0008810573

You can see that each party has a few members who seem to play an important role/position in this social network. An interesting finding could be that the two largest parties in the current parliament, CDU/CSU and SPD, do not have as many members in the first places as you might expect. These places are rather taken by smaller parties like AfD, FDP, Die Linke. These unexpected results should be further investigated in the future to find the reason for this. Possible explanations could be the difference between opposition and government parties, different communication strategies of the parties or the adoption rate of social media in each party.

In a big picture this network analysis can confirm that many of the expected relationships within each party and between the parties can also be shown in social media. In the future, this analysis could be further strengthened by also examining how politicians have interacted with each other through retweets, answers or the liking of other posts of politicians. It should also be further investigated why certain politicians are particularly important for this network and whether it is possible to draw conclusions about their power within their party.

For the people who are interested in the actual code, I have put the most important parts into the appendix. If you would like to receive the underlying data or have further questions, please send me a message on LinkedIn.

The Code

Capture the data from Twitter


appname <- 'Research Politicians'
key <- 'Input your own key'
secret <- 'Input your own key'
access_token <- 'Input your own key'
access_secret <- 'Input your own key'

twitter_token <- create_token(
  app = appname,
  consumer_key = key,
  consumer_secret = secret,
  access_token = access_token,
  access_secret = access_secret)

name_ politician <- read.csv('list_ politician.csv',header = FALSE)

i = 0
user_follows_list_var = ()
user_follows_list = ()

while (i<=len(name_ politician[1]) {
  user_follows_list_var <- get_friends(list_pol[i])
  user_follows_list <- rbind(user_follows_list,user_follows_list_var)
  user_follows_list_var <- c()
  if (i%%15==0) {
  i <- i + 1

user_follows = data.frame(user_follows_list)

colnames(name_ politician) <- c('user_id','user')
joined_data <- left_join(user_follows, name_politician,by='user')

fwrite(joined_data, file='twitter_relation.txt',sep = '\t')

fwrite(name_politician,file='twitter_account.txt',row.names = FALSE,sep = '\t')

Social Network Analysis

relation <- read.csv('twitter_relation.txt',sep = '\t')
account <- read.csv('twitter_account.txt',sep = '\t')
graph_politician <-
get.edge.attribute(graph_politician, 'weight')


tail(sort(betweenness(graph_politician)), 10)
tail(sort(closeness(graph_politician)), 10)


Lukas Tatge

Lukas Tatge

Lukas Tatge heads CorrelAidX Göttingen. He is a Master student of Global Business/Management.