Bevor wir mit der Auswertung der Tweets beginnen, laden wir zunächst alle relevanten Packete und Daten.

library(tidyverse)
library(lubridate)
library(rtweet)
library(ggmap)
library(knitr)      # wird nur für die Darstellung der Tabellen benötigt
library(kableExtra) # ebenfalls
require(scales)

mep_tweets <- readRDS("data/mep_tweets.RDS")
mep_positions <- readRDS("data/mep_positions.RDS")
mep_details <- readRDS("data/mep_details_clean.RDS")
ep_committees <- readRDS("data/ep_committees.RDS")

mep_tweets <- mep_tweets %>%
  mutate(lower_screen_name = str_to_lower(screen_name)) %>%
  left_join(mep_details %>% select(screen_name, party, group_short, country) %>%
              mutate(country_ep = country), by = c("lower_screen_name" = "screen_name")) %>%
  select(-lower_screen_name)

Nachdem wir nun alle Daten gezogen haben, können wir die Tweets nun nach Fraktionszugehörigkeit, Parteizugehörigkeit, Land und Ausschüssen auswerten. Wir haben bereits gesehen, dass sich in der EVP die meisten MEPs mit Twitteraccounts finden. Uns interessiert nun, wie viele Tweets pro Tag denn von jedem Abgeordneten veröffenlticht werden.

Hierfür nutzen wir unter anderem das Paket lubridate. Wir errechnen uns die Mittelwerte für die Tweets pro Tag und

mep_tweets %>%
  mutate(day = as_date(created_at)) %>%
  group_by(screen_name, group_short, day) %>%
  summarise(tweets = n()) %>%
  group_by(screen_name, group_short) %>%
  summarise(tweets_per_day_mean = mean(tweets)) %>%
  ggplot(aes(x = group_short, fill = group_short, y = tweets_per_day_mean)) +
  geom_boxplot() +
  theme_minimal() + 
  guides(fill = FALSE) +
  labs(title = "Durchschnittliche Tweets pro Tag nach Account und Fraktion",
       subtitle = "Twitternde MEPs im Europäischen Parlament",
       x = "Fraktion",
       y = "Durchschnittliche Tweets pro Tag")

Da haben wir einen ziemlichen Ausreißer dabei. Es handelt sich um den Account von Michał Boni - mit insgesamt 117.000 Tweets auch Spitzenreiter in den Tweets im EP. Seine hohe Twitterfrequenz bedeuten auch, dass wir lediglich etwa 16 Tage in die Vergangenheit gucken können. Twitter begrenzt uns ja auf die Analyse der letzten 3.200 Tweets.

Wir filtern ihn raus und vergleichen dann die Werte.

mep_tweets %>%
  filter(screen_name != "MichalBoni") %>%
  mutate(day = as_date(created_at)) %>%
  group_by(screen_name, group_short, day) %>%
  summarise(tweets = n()) %>%
  group_by(screen_name, group_short) %>%
  summarise(tweets_per_day_mean = mean(tweets)) %>%
  ggplot(aes(x = reorder(group_short, -tweets_per_day_mean, FUN = median), fill = group_short, y = tweets_per_day_mean)) +
  geom_boxplot() +
  theme_minimal() + 
  guides(fill = FALSE) +
  labs(title = "Durchschnittliche Tweets pro Tag nach Account und Fraktion",
       subtitle = "Twitternde MEPs im Europäischen Parlament",
       x = "Fraktion",
       y = "Durchschnittliche Tweets pro Tag")

Das Ergebnis: Die (euroskeptischen) Abgeordneten der ENF und EFDD twittern durchschnittlich am häufigsten pro Tag – aber bei der ENF und EFDD finden sich eben auch die wenigsten Accounts. Heißt: Wenn sie twittern, twittern sie viel. Die Abgeordneten der EVP twittern durchschnittlich am wenigsten.

Die beliebtesten und reichweitestärksten Tweets

Wir können auch die beliebtesten und reichweitestärksten Tweets analysieren, indem wir uns die Anzahl der Favorites und Retweets untersuchen:

mep_tweets %>%
  select(screen_name, text, favorite_count) %>%
  arrange(-favorite_count) %>%
  head(10) %>%
  kable() %>%
  kable_styling() %>%
  column_spec(1, bold = TRUE, border_right = TRUE)
screen_name text favorite_count
guyverhofstadt “Just tell us what Vladimir has on you. Maybe we can help.” https://t.co/DLc7YJFXqT 108932
SebDance

Ending free movement.

On the left: your current free zone. You can work, travel, study, love, retire across this area. No visas. Includes non-EU members.

On the right: your future free zone (assuming CTA with Ireland).

Can anyone explain how this is increasing opportunity? https://t.co/vXoe2pnkWw
33326
GerardBattenMEP This Tweet from @GerardBattenMEP has been withheld in: Germany, France. 32776
guyverhofstadt Clearly the EU still inspires some in the UK 😊 #QueensSpeech https://t.co/vqTWnxKk1V 24029
guyverhofstadt If we had known in advance that blue was so important to the UK, we could simply have replaced our passports by this one 😊 https://t.co/fnUiLowyq7 22889
guyverhofstadt Farage portrait unsold: my trust in the taste of the British people is greater than ever 😉 https://t.co/8238N7qUXw 18570
guyverhofstadt Instead of throwing dead fish in the Thames, Nigel Farage should have done his job as a member of the fisheries committee in the European Parliament, as I told him already years ago! https://t.co/yKU8AX8dig https://t.co/8XbkSjBpOe 18326
guyverhofstadt Emotional to see so many people from all walks of life marching for a different future. Politicians might take Britain out of the EU, but it won’t stop people feeling European. #PeoplesVoteMarch #IamEuropean https://t.co/zNy554NDin 17025
guyverhofstadt There is no EU legislation dictating passport colour. The UK could have had any passport colour it wanted and stay in the EU https://t.co/bkQX0T0F2Q 16894
guyverhofstadt On Brexit, we will never accept discrimination based on skills and nationality. We will never accept an extension on article 50. Enough mess has been created by Brexit. Let’s stop it! We will never undermine the principles of our Union to rescue the Tory party 🇪🇺 🇬🇧 https://t.co/7uD4Scw03j 16279
mep_tweets %>%
  filter(is_retweet == FALSE) %>%
  select(screen_name, text, retweet_count) %>%
  arrange(-retweet_count) %>%
  head(10) %>%
  kable() %>%
  kable_styling() %>%
  column_spec(1, bold = TRUE, border_right = TRUE)
screen_name text retweet_count
guyverhofstadt “Just tell us what Vladimir has on you. Maybe we can help.” https://t.co/DLc7YJFXqT 37452
ramontremosa

El video que en Madrid no quieran que veas sobre la #Diada18:

Haz RT para que llegue a todos los rincones de España. https://t.co/gsuU3W9QPw
18341
SebDance

Ending free movement.

On the left: your current free zone. You can work, travel, study, love, retire across this area. No visas. Includes non-EU members.

On the right: your future free zone (assuming CTA with Ireland).

Can anyone explain how this is increasing opportunity? https://t.co/vXoe2pnkWw
18185
GerardBattenMEP This Tweet from @GerardBattenMEP has been withheld in: Germany, France. 14139
guyverhofstadt There is no EU legislation dictating passport colour. The UK could have had any passport colour it wanted and stay in the EU https://t.co/bkQX0T0F2Q 11211
MarinaAlbiol No falla: llega el debate sobre abusos bancarios y derecho a la vivienda y los eurodiputados del PP y PSOE desaparecen de la reunión 🤔 https://t.co/MJW53hsB7y 10254
guyverhofstadt Instead of throwing dead fish in the Thames, Nigel Farage should have done his job as a member of the fisheries committee in the European Parliament, as I told him already years ago! https://t.co/yKU8AX8dig https://t.co/8XbkSjBpOe 10246
LolaPodemos He estado en Ecuador, y voy a contar lo que he visto. El mayor crimen medioambiental de la Historia: Texaco en la Amazonía. Abro HILO 👇 https://t.co/GIw2v3wMXl 9654
MarinaAlbiol Entre insultos y gritos de “Viva el Rey”, he deseado que Catalunya sea lo que decidan los catalanes y traiga el fin de la monarquía #4Oct https://t.co/ae02JUJCw8 9645
guyverhofstadt Share if you feel the same. https://t.co/zEs67FX6GA 9195

Sprache der Tweets

Wir merken heir schon, dass die meisten tweets war in englisch verfasst sind, aber einge Tweets auch in anderen Sprachen geschrieben wurde. Deshalb wollen wir mal analysieren, in welcher Sprache eigentlich die meisten Tweets geschrieben sind. Hierfür nutzen wir das Paket cld2 (Compact Language Detector 2). Dieser Algorithmus funktioniert sehr schnell und wir können die 1,1 Million Tweets in wenigen Sekunden einer Sprache zuordnen.

library(cld2)

mep_tweets <- mep_tweets %>%
  mutate(language_tweet = detect_language(text))

Nun können wir uns ausgeben lassen, in welcher Sprache die meisten Tweets geschrieben wurden.

mep_tweets %>%
  group_by(language_tweet) %>%
  summarise(tweets = n()) %>%
  mutate(proportion = tweets/nrow(mep_tweets)) %>%
  arrange(-proportion) %>%
  mutate(proportion = scales::percent(proportion))
## # A tibble: 71 x 3
##    language_tweet tweets proportion
##    <chr>           <int> <chr>     
##  1 en             370891 32.9%     
##  2 fr             130963 11.6%     
##  3 it             106595 9.5%      
##  4 de              85271 7.6%      
##  5 <NA>            81495 7.2%      
##  6 es              74322 6.6%      
##  7 nl              45667 4.1%      
##  8 pl              40776 3.6%      
##  9 sv              30090 2.7%      
## 10 el              26229 2.3%      
## # ... with 61 more rows

Die meisten Tweets wurden in englisch oder französisch verfasst. Allerdings bin ich doch etwas überrascht, dass lediglich 32,9% der Tweets englisch sind. Etwa 7% der Tweets konnten keiner Sprache zugeordnet werden. Das Algorithmus des Package cld2 arbeitet zwar schnell, aber nicht besonders akkurat. Es könnte also sein, dass hier viele Tweets auch falsch zugeordnet sind. Insbesondere die exotischeren Sprachen.

Gucken wir uns mal die Verteilung der Sprachen (englische vs. nicht-englische Tweets) nach Fraktionen an.

mep_tweets %>%
  mutate(language_en = ifelse(language_tweet == "en", "english", "not english")) %>%
  group_by(group_short, language_en) %>%
  summarise(tweets = n()) %>%
  na.omit() %>%
  ggplot(aes(x = group_short, fill = language_en, y = tweets)) +
  geom_bar(stat="identity", position = "dodge") +
  labs(title = "Sprache der Tweets nach Fraktion",
       subtitle = "Twitternde MEPs im Europäischen Parlament",
       y = "Tweets",
       x = "Fraktion", 
       fill = "Sprache") +
  theme_minimal()

Wenig überraschend: In der rechtsextremen ENF Fraktion finden sich kaum englische Tweets. In allen anderen Fraktionen dominieren die englischsprachigen Tweets – wobei vermutlich auch ein großer Teil auf Muttersprachler zurückzufrühren ist.

Hashtags

Wir gucken uns zuletzt noch an, welche Hashtags in den einzelnen Fraktionen am häufigsten genutzt werden.

mep_tweets %>%
  select(hashtags) %>%
  unnest() %>%
  na.omit() %>%
  group_by(hashtags) %>%
  summarise(count = n()) %>%
  arrange(-count)
## # A tibble: 152,726 x 2
##    hashtags count
##    <chr>    <int>
##  1 EU       13624
##  2 Brexit   12565
##  3 EPlenary  6769
##  4 UE        6050
##  5 TTIP      4734
##  6 Europa    4730
##  7 Europe    4650
##  8 CETA      4624
##  9 EP        4295
## 10 dkpol     4071
## # ... with 152,716 more rows

Und nach Fraktionen:

mep_tweets %>%
  select(group_short, hashtags) %>%
  unnest() %>%
  group_by(group_short, hashtags) %>%
  summarise(used = n()) %>%
  na.omit() %>%
  top_n(5, used) %>%
  ggplot(aes(x = hashtags, -used, y = used)) +
  geom_col() +
  coord_flip() +
  facet_wrap(~group_short, scales = "free") +
  theme_minimal() +
  labs(title = "Die beliebtesten Hashstags nach Fraktionen",
       subtitle = "Twitternde MEPs im Europäischen Parlament")

Interessant: In der Fraktion ENF ist migrants der am häufigsten genutzte Hashtag. Wir tauchen jetzt nicht tiefer in die Daten ein.

Woher kommen die Tweets?

Wir können die Geolocation in den Tweets nutzen, um sie auf einer Europakarte darzustellen. Wir nutzen hierfür das Packet maps.

europe_map <- get_map(location='Europe', zoom=4)

tweet_location <- lat_lng(mep_tweets) %>%
  select(group_short, lat, lng) %>%
  na.omit()

Insgesamt haben 32565 Tweets eine Location hinterlegt.

ggmap(europe_map, extent = "device") +
  geom_point(aes(x = lng, y = lat), data = tweet_location, alpha = 0.5)

Wenig überraschen: Sehr viele Tweets in BeNeLux und Italien. Weniger Tweets in Deutschland. Wir können uns aber auch angucken, welche Fraktionen vorwiegend aus welchem Land tweeten:

ggmap(europe_map, extent = "device") +
  geom_point(aes(x = lng, y = lat, colour = group_short), data = tweet_location, alpha = 0.5) +
  facet_wrap(~group_short) +
  guides(colour = FALSE)

Wir könnten jetzt noch weiter arbeiten und dann auch die Ausschüsse mit einbeziehen, allerdings kümmere ich mich um dieses Thema zu einem anderen Zeitpunkt.