Czy preferencje polityczne mają jakiś związek z preferencjami sportowymi? Innymi słowy: czy jeśli lubię PSL to wolę piłkę nożną czy jednak bieganie?
Stereotypowo mogłoby to wyglądać tak: Nowoczesna to biegi, PiS – piłka nożna i podnoszenie ciężarów (przed tv, ciężary 500ml w puszce), Kukiz – wędkarstwo, PSL – wypas owiec. Koniec żartu, można się śmiać.
A jak jest? Zrobimy eksperyment z dużą ilością danych. Facebook ma to od ręki, dlatego wykorzystamy publiczne informacje z tego właśnie źródła. Poza tym – te 2 miliardy użytkowników zostawia bardzo dużo informacji o sobie. Według badania Gemius/PBI za kwiecień 2017 w Polsce z Facebooka korzysta 22.6 mln internautów (81.4% wszystkich, co ciekawe – zanotowano spadek o ponad 200 tys. m/m).
Jak to zrobić? Po pierwsze trzeba wytypować listę fanpage’y na podstawie których będziemy wyciągać wnioski. Skorzystałem z dwóch źródeł: własnej głowy (i sondaży poparcia) aby wytypować partie i z własnych rąk aby wyszukać ich fanpages na Facebooku. Druga strona równania to lista fanpage’y sportowych (dla mnie trudniejsze) – tutaj skorzystałem z raportów Sotrender.
Teraz metodologia. Można na kilka sposobów. Na przykład biorąc listę fanów poszczególnych stron i szukając części wspólnych tych zbiorów. Tak będziemy działać. Problemem jest tylko jak uzyskać listę fanów? Kiedyś Facebook udostępniał poprzez API możliwość wywoływania zapytań FQL (to taki podobny do SQL język dla FB). Ale ograniczenia prywatności spowodowały, że to nie działa. Trzeba więc inaczej, co nieco zaburzy wyniki (trudno mi jednocześnie na szybko oszacować jak bardzo).
Posty na stronach są publiczne, ludzie lajkują i komentują. Facebook udostępnia poprzez API dane o tych komentarzach i lajkach, w tym ID (oraz imię i nazwisko) użytkowników, którzy taką interakcję poczynili. Zatem weźmiemy posty każdej ze stron, dla każdego postu listę osób reagujących (policzymy tylko like i comment – bez share oraz innych reakcji) na post. Tym sposobem nie będziemy mieć fanów (jest ich zapewne więcej niż wchodzących w interakcję – jaka to różnica wyjdzie po drodze; a jednocześnie na tych stronach można komentować i lajkować nie będąc jednocześnie fanem strony), ale coś podobnego. Może nawet lepszego (użytkownik zaangażowany jest cenniejszy niż bierny obserwator).
Pobranie danych
Na początek lista fanpage’ów:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
fbpages <- c( # partie "pisorgpl", "PlatformaObywatelska", "Nowoczesna.oficjalnie", "KlubPoselskiKukiz15", "nowePSL", "partiarazem", "sojusz", "janusz.korwin.mikke", "KomitetObronyDemokracji", # sport "rl9official", "KubaBlaszczykowski", "chodakowskaewa", "OfficialLukaszPiszczek", "fitpl", "KochamFootball", "419219738138922", "arekmilik99", "AgnieszkaRadwanska1", "MMAmedKhalidov", "LaczyNasPilka", "kibicujjustynie", "KamilStochOfficial", "GrzegorzKrychowiakOfficial", "274911289215982", "Sportpl", "robertburneika", "onetsport", "przegladsportowy", "lechpoznan.oficjalna", "ekstraklasatrolls", "SportoweFakty", "maciejkot.official", "FangolPl", "joanna.jedrzejczyk", "GlikOfficial", "TurboGrosik", "rowerowe.porady", "PoznanMaraton", "MichalPazdanOfficial") |
Teraz czas na maszynę, która zgarnie z FB to czego potrzebujemy. Najpierw posty z każdej z wyżej wymienionych stron, później dla każdego postu ID użytkowników wchodzących w interakcje. Danych jest bardzo dużo – najwięcej lajków i komentarzy wśród zebranych ma post (jeszcze nie mam tych danych, a już wiem – ot, zagadka):
Fanpage | Treść postu | Liczba like | Liczba komentarzy |
---|---|---|---|
Robert Lewandowski | Today we have become parents of Klara. Thank you Anna Lewandowska for endurance! <3 Proud Daddy |
374006 | 20343 |
Zatem dla tylko tego jednego postu pobierzemy prawie 400 tysięcy IDków! Ogrom danych. W pamięci tego nie da się trzymać. Wykorzystamy bazę danych, taką najprostszą – SQLite. Jest to po prostu plik na dysku. Ważne, że nie w pamięci (chociaż może być w pamięci). U mnie ten plik dla powyższych 39 fanpage’y i po 100 najnowszych postów zajął około 1.2 GB. Całość zbierała się kilkanaście godzin. Wszystko poniższym kodem:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
library(Rfacebook) library(tidyverse) ##### TOKEN DO FB ##### # numery z aplikacji FB fb_app_id = "xxxx" fb_app_secret = "yyyy" # tworzymy token aplikacji i zapisujemy do lokalnego pliku fb_oauth <- fbOAuth(app_id = fb_app_id, app_secret = fb_app_secret) save(fb_oauth, file="fb_token.RData") # w przyszłości nie trzeba tworzyć tokena - wystarczy wczytać już zapisany load("fb_token.RData") ##### ##### FUNKCJE ##### get_fanpage_posts <- function(fb_page_name, n = 100, token) { # funkcja pobierze n najnowszych postów z fanpage fb_page_name # najnowsze posty z fanpage fb_page_posts <- getPage(fb_page_name, token=token, n=n) # usuwamy zbędne kolumny fb_page_posts <- fb_page_posts %>% select(-story, -link) return(fb_page_posts) } get_post_data <- function(post_id, token, n) { # fukncja pobiera ID użytkowników, którzy dali like lub skomentowali wpis # weź wszystkie dane o wpisie post <- getPost(post_id, token = token, n = n) # potrzebne nam tylko ID userów lajkujących if(!is.null(post$likes)) post_likes <- post$likes %>% select(from_id) # i ID userów komentujących if(!is.null(post$comments)) post_comments <- post$comments %>% select(from_id) # tylko unikalne - jak ktoś dał like i komentarz policzony będzie tylko raz post_data <- rbind(post_likes, post_comments) %>% distinct() # z jakiego fanpage pochodzi post? post_data$fb_page_id <- post$post$from_id return(post_data) } ##### ##### Gdzie zapisujemy dane? ##### sqlsc <- src_sqlite("fb_posts.sqlite", create = TRUE) ##### ##### POBRANIE POSTÓW ##### # pobierz po 100 ostatnich postów z każdej ze stron n_posts <- 100 for(i in 1:length(fbpages)) { tmp <- get_fanpage_posts(fbpages[i], n_posts, fb_oauth) db_insert_into(sqlsc$con, "fb_posts", tmp) } rm(tmp) ##### ##### POBRANIE USER_ID LIKE'OW i KOMENTARZY ##### fb_page_posts <- tbl(sqlsc, "fb_posts") # lista postów, z których pobierzemy dane fb_page_posts_local <- fb_page_posts %>% select(id, likes_count, comments_count) %>% distinct() %>% collect() n_rows <- nrow(fb_page_posts_local) ##### pobierz lajkujących i komciujących pobrane posty ##### for(i in 1:n_rows) { # pobierz dane o poście tmp <- get_post_data(fb_page_posts_local[i, "id"], fb_oauth, fb_page_posts_local[i, "likes_count"] + fb_page_posts_local[i, "comments_count"]) # zapisz w bazie db_insert_into(sqlsc$con, "users_actions", tmp) } |
Po wykonaniu powyższego kodu w bazie sqlsc mamy dwie tabele: fb_page_posts oraz fb_user_actions. Pierwsza zawiera dane o postach, druga o ID użytkowników, którzy weszli w interakcję z danym fan_page.
Kiedy i co publikują strony?
Na początek rozgrzewka – zobaczmy kiedy powstają posty na poszczególnych stronach:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
library(lubridate) theme_set(theme_minimal()) fb_page_posts %>% select(from_name, created_time) %>% collect() %>% mutate(created_time = ymd_hms(created_time), hour = hour(created_time)) %>% count(hour, from_name) %>% ggplot() + geom_line(aes(hour, n, color=from_name), show.legend = FALSE) + facet_wrap(~from_name) + labs(x="Godzina publikacji postu", y="Liczba postów (suma)") |
Mniej więcej równomiernie, raczej nie w nocy. Niektóre strony mają piki w określonych porach. SLD publikuje rano (co, to się przekonamy niedługo, ale mogę zdradzić, że są to zapowiedzi wystąpień przedstawicieli partii w mediach), Poznań Maraton zapewne publikował informacje o starcie i zakończeniu imprezy. Piotr Żyła – po zakończeniu zawodów.
Co komentują i lajkują ludzie?
Najpierw lajki (średnia lajków na post liczona jako suma like podzielona przez sumę postów):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
fb_page_posts %>% select(from_name, type, likes_count) %>% filter(!type %in% c("event", "note")) %>% group_by(from_name, type) %>% summarise(m_likes = sum(likes_count), n = n()) %>% ungroup() %>% collect() %>% ggplot() + geom_bar(aes(from_name, m_likes/n, fill=type), stat = "identity") + facet_wrap(~type, ncol = 6) + coord_flip() + labs(x="Fan page", y="Średnia liczba like'ów", fill="Typ postu") + theme(axis.text.x = element_text(angle=90)) |
U Lewandowskiego dominują zdjęcia (szczególnie jedno), co jest dość naturalną tendencją (zobaczymy za moment). A komentarze? Też średnie:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
fb_page_posts %>% select(from_name, type, comments_count) %>% filter(!type %in% c("event", "note")) %>% group_by(from_name, type) %>% summarise(m_comments = sum(comments_count), n = n()) %>% ungroup() %>% collect() %>% ggplot() + geom_bar(aes(from_name, m_comments/n, fill=type), stat = "identity") + facet_wrap(~type, ncol = 6) + coord_flip()+ labs(x="Fan page", y="Średnia liczba komentarzy", fill="Typ postu") + theme(axis.text.x = element_text(angle=90)) |
Zobaczmy jeszcze jak wygląda całkowita średnia liczba komentarzy i lajków w zależności od typu postu:
1 2 3 4 5 6 7 8 9 10 |
fb_page_posts %>% select(type, comments_count, likes_count) %>% group_by(type) %>% summarise(m_comments = sum(comments_count), m_likes = sum(likes_count), n = n()) %>% ungroup() %>% transmute(type, n, p_comments = round(m_comments/n, 1), p_likes = round(m_likes/n, 1)) |
Typ postu | Liczba postów | Średnia komentarzy | Średnia like |
---|---|---|---|
event | 14 | 17.8 | 668.2 |
link | 1011 | 23.5 | 567.0 |
note | 1 | 64.0 | 2417.0 |
photo | 2112 | 203.4 | 12243.7 |
status | 91 | 122.9 | 4023.8 |
video | 644 | 143.8 | 2654.7 |
Jak widać najwięcej interakcji zdobywają zdjęcia, później zwykłe posty (statusy), a na koniec wideo. To wyszło już wcześniej, przy badaniu działań serwisów informacyjnych, ale może wtedy tego nie napisałem? ;-)
Wynik w dużej mierze robi post Lewandowskiego z nowo narodzoną córką, po odrzuceniu tej strony mamy:
Typ postu | Liczba postów | Średnia_komentarzy | Średnia like |
---|---|---|---|
event | 14 | 17.8 | 668.2 |
link | 1010 | 23.4 | 551.6 |
note | 1 | 64.0 | 2417.0 |
photo | 2016 | 173.5 | 8429.9 |
status | 91 | 122.9 | 4023.8 |
video | 641 | 143.2 | 2580.8 |
O czym strony piszą najczęściej?
Sprawdźmy jakie słowa występują w postach najczęściej. Do tego potrzebujemy treści postów, podzielenia jej na pojedyncze słowa i policzenia ile ich jest. Przy okazji wyrzucimy linki.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
library(tidytext) # stop words pl_stopwords <- read_lines("../textmining/polish_stopwords.txt") pl_stopwords <- c(pl_stopwords, "www.partiarazem.pl", "godz", "np", "goo.gl") pl_stopwords <- unique(pl_stopwords) # usuwamy URLe fb_messages <- fb_page_posts %>% select(from_name, message) %>% collect(n = Inf) %>% mutate(message = gsub("(f|ht)tp\\S+\\s*", "", message)) %>% mutate(message = gsub("_", "", message)) %>% filter(!is.na(message)) |
Mając tabelę z nazwą strony i treściami poszczególnych jej postów możemy policzyć wystąpienia poszczególnych słów i usunąć słowa nic nie wnoszące do treści (chociażby spójniki) – tzw. stopwords (i przy okazji zostawimy tylko słowa dłuższe niż 2 znaki):
1 2 3 4 5 6 7 |
word_list <- fb_messages %>% unnest_tokens(text, message, token = "words") %>% filter(!text %in% pl_stopwords) %>% # polskie stopwords filter(!text %in% stop_words$word) %>% # stopwords z biblioteki tidytext filter(nchar(text) > 2) %>% count(from_name, text) %>% ungroup() |
Jakie słowa są najpopularniejsze na wszystkich fanpages, z których mamy posty?
1 2 3 4 5 6 |
library(wordcloud) wordcloud(word_list$text, word_list$n, max.words = 100, scale = c(2, 0.2), colors = RColorBrewer::brewer.pal(12, "Paired")) |
Przepisy, jak rany! “Wymieszaj szczyptę tłuszczu na marsz wolności”, ktoś tutaj bruździ, co nie? Zobaczmy chmurki per strona:
1 2 3 4 5 6 7 8 9 10 |
by(word_list, word_list$from_name, function(x) { wordcloud(x$text, x$n, max.words = 100, scale = c(3, 0.2), colors = RColorBrewer::brewer.pal(12, "Paired")) text(0.1, 0.95, unique(x$from_name), col="black", cex=1.3, adj=c(0,0)) } ) |
Za mieszanie tłuszczu łyżeczkami odpowiada Ewa Chodakowska.
Wśród partii wygląda to mniej więcej tak, że każdy pisze o sobie i o PiSie.
Indeks aktywności
Sprawdźmy teraz czy na jednych stronach ludzie są bardziej aktywni niż na innych. Na początek policzmy ile mamy użytkowników (unikalnych), którzy coś zrobili na fanpage (dali lajka albo skomentowali). Te dane nie są duże, możemy je trzymać w pamięci:
1 2 3 4 5 6 |
fb_user_interactions <- fb_user_actions %>% distinct() %>% group_by(fb_page_id) %>% summarise(n=n()) %>% ungroup() %>% collect() |
Potrzebujemy jeszcze powiązania numeru ID strony z jej nazwą oraz przyda się oznaczenie czy dany fanpage jest “partyjny” czy “sportowy” (to już ręcznie):
1 2 3 4 5 6 7 8 9 10 11 |
fb_page_names <- fb_page_posts %>% select(from_id, from_name) %>% distinct() %>% collect() fb_partie <- c("102931488739", "137877409609952", "157458232131", "1662770490627705", "177473808919", "277681892059", "328170794051845", "430323810469014", "467218110099782") fb_page_names <- fb_page_names %>% mutate(fb_type = ifelse(from_id %in% fb_partie, "partia", "sport")) |
U kogo było najwięcej aktywności (sumarycznie – to jeszcze nie jest żaden wskaźnik)?
1 2 3 4 5 6 7 |
fb_user_interactions <- left_join(fb_user_interactions, fb_page_names, by=c("fb_page_id"="from_id")) fb_user_interactions %>% arrange(desc(n)) %>% select(from_name, n, fb_type) %>% head(10) |
Fanpage | Liczba interakcji | Kategoria |
---|---|---|
Robert Lewandowski | 1881507 | sport |
Kamil Stoch – Oficjalna strona | 716377 | sport |
Kuba Błaszczykowski | 598798 | sport |
Piotr Żyła- Official | 598169 | sport |
Arek Milik | 475582 | sport |
Michał Pazdan | 453650 | sport |
Grzegorz Krychowiak | 336864 | sport |
Agnieszka Radwanska | 307423 | sport |
Maciej Kot | 271161 | sport |
Joanna Jedrzejczyk | 236075 | sport |
Jak widać pierwsza dziesiątka to sport, a tak wygląda to wśród partii:
Fanpage | Liczba interakcji |
---|---|
Janusz Korwin-Mikke | 55790 |
Kukiz ’15 | 48523 |
Platforma Obywatelska | 34772 |
Razem | 25592 |
Komitet Obrony Demokracji | 21928 |
Prawo i Sprawiedliwość | 17332 |
Nowoczesna | 7682 |
Sojusz Lewicy Demokratycznej | 5454 |
Polskie Stronnictwo Ludowe | 1481 |
Jednak sumaryczna liczba interakcji to za mało, żeby określić czy społeczność skupiona wokół danej strony jest bardziej aktywna niż wokół innej. Zestawmy to z liczbą fanów strony.
Ile fanów mają strony?
Tutaj zaczyna się problem. Facebook API w wersji 2.5 pozwalał po prostu zapytać o liczbę polubień strony, w wersjach późniejszych nie jest tak łatwo. Dodatkowo, jeśli używamy tokena z aplikacji to Facebook narzuca nam wersję API (w tym momencie v2.9). Da się to obejść.
Na stronie pobieramy sobie klucz tymczasowy i wpisujemy go do zmiennej token poniżej. W pętli pobieramy kolejne ID stron, budujemy zapytanie, które bezpośrednio ślemy do API Facebooka. Z odpowiedzi pobieramy liczbę fanów (lajków).
1 2 3 4 5 6 7 8 9 10 11 12 13 |
library(Rfacebook) load("fb_token.RData") token = "xxxxxxxxx" fb_user_interactions$likes <- NA for(i in 1:nrow(fb_user_interactions)) { query <- paste0("https://graph.facebook.com/v2.5/", as.character(fb_user_interactions[i, "fb_page_id"]), "?fields=likes") fb_user_interactions[i, "likes"] <- callAPI(query, token)$likes } |
Teraz możemy policzyć stosunek sumy interakcji do liczby fanów:
1 2 3 4 5 |
fb_user_interactions %>% mutate(index = round(100*n/likes, 1)) %>% select(from_name, index) %>% arrange(desc(index)) %>% head(10) |
Fanpage | index |
---|---|
Michał Pazdan | 98.6 |
Kamil Stoch – Oficjalna strona | 76.4 |
Maciej Kot | 70.7 |
Piotr Żyła- Official | 52.8 |
Kamil Grosicki | 46.2 |
Joanna Jedrzejczyk | 43.8 |
Arek Milik | 43.4 |
Poznań Maraton | 41.9 |
Grzegorz Krychowiak | 39.5 |
Agnieszka Radwanska | 31.9 |
Znowu przoduje sport – z policzonego wskaźnika wynika, że prawie 99% fanów strony Michała Pazdana reaguje na wpisy. Piękny wynik. Ale to nie muszą być tylko fani – ja nie będąc fanem mogę dać na tym fanpage like i napisać komentarz. Tak jest w przypadku właściwie wszystkich stron.
Jak to wygląda dla partii:
Fanpage | index |
---|---|
Platforma Obywatelska | 28.9 |
Razem | 28.6 |
Kukiz ’15 | 17.4 |
Sojusz Lewicy Demokratycznej | 13.3 |
Polskie Stronnictwo Ludowe | 10.6 |
Prawo i Sprawiedliwość | 9.5 |
Komitet Obrony Demokracji | 8.6 |
Nowoczesna | 7.7 |
Janusz Korwin-Mikke | 7.1 |
Jak widać zdecydowanie słabiej. Co ciekawe – najwięcej aktywności było na fanpage’u Korwina, a to tylko 7% liczby fanów.
Współinterakcje
Dochodzimy do postawionego na samym początku pytania: na jakich sportowych fanpage’ach udzielają się ci, którzy udzielają się na stronach poszczególnych partii?
Potrzebujemy listę użytkowników udzielających się na stronie partii – to będzie łatwe, wystarczy prosty filtr, zbudujemy do tego funkcję (uniwersalną – dla każdego fanpage w naszej bazie):
1 2 3 4 5 6 7 8 9 |
page_users <- function(page_id) { users <- fb_user_actions %>% filter(fb_page_id == page_id) %>% select(user_id = from_id) %>% distinct() %>% collect(n = Inf) return(users$user_id) } |
Teraz ze wszystkich interakcji wyjmujemy te, których podjęły się osoby z tej listy. I liczymy jaka to była część wszystkich interakcji na danej stronie. Znowu funkcja:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# liczba interakcji per strona interact_all <- fb_user_actions %>% group_by(fb_page_id) %>% summarise(n_all=n()) %>% ungroup() interactions_page <- function(user_list) { interact_page <- fb_user_actions %>% filter(from_id %in% user_list) %>% group_by(fb_page_id) %>% summarise(n_page=n()) %>% ungroup() interact <- left_join(interact_all, interact_page, by="fb_page_id") %>% select(fb_page_id, n_page, n_all) %>% collect() %>% mutate(percent = n_page / n_all) %>% select(fb_page_id, percent) return(interact) } |
Teraz z pętli przejdziemy strona po stronie i zbudujemy sobie tabelę “każdy z każdym”. Tabela wynikowa jest nieduża, ale jej wygenerowanie sporo trwa.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
interactions <- data.frame() for(i in 1:nrow(fb_page_names)) { cat(paste()) users <- page_users(as.character(fb_page_names[i, "from_id"])) interact <- interactions_page(users) interact$fb_page_from <- as.character(fb_page_names[i, "from_id"]) interactions <- rbind(interactions, interact) } # dodajemy nazwy zamiast numerów fanpages interactions <- left_join(interactions, fb_page_names, by=c("fb_page_id"="from_id")) %>% rename(b_name = from_name, b_type = fb_type) %>% left_join(fb_page_names, by=c("fb_page_from"="from_id")) %>% rename(a_name = from_name, a_type = fb_type) |
Zobaczmy co z tego wychodzi? Z wykresu wyłączyć należy przekątną – oczywiste jest, że 100% aktywnych na danej stronie jest… na niej aktywnych :) Dzięki temu wyłączeniu skala kolorów nie będzie taka płaska (maksimum nie przy 100% a na przykład 80%).
1 2 3 4 5 6 7 8 9 |
interactions %>% filter(a_name != b_name) %>% ggplot() + geom_tile(aes(a_name, b_name, fill=100*percent), color="lightgray") + scale_fill_gradient(low="darkgreen", high="red") + labs(y="Aktywni na stronie...", x="...są też aktywni na stronie", fill="Procent\nużytkowników\nwchodzących\nw interakcje\nna fanpage") + theme(axis.text.x = element_text(size=7, angle=90, hjust=1, vjust=0), axis.text.y = element_text(size=7)) |
Czy teza postawiona na początku, że Nowoczesna to biegi, PiS – piłka nożna i browary, Kukiz – wędkarstwo, a PSL – wypas owiec jest prawdziwa? No aż tak nie jesteśmy w stanie tego zweryfkować (nie mamy informacji o fanpages dotyczących wędkarstwa czy wypasu owiec, znanych i craftowych browarów też nie badaliśmy). Ale mamy gotowe narzędzie, wystarczy tylko go użyć.
Co zatem widać z powyższego diagramu?
- 22% użytkowników facebooka, którzy poczynili aktywność na stronie PiSu zrobiło też aktywność na stronie Kamila Stocha, wśród partii – najwięcej działają na stronach Kukiz’15
- wśród użytkowników gratulujących Lewandowskiemu córki są tacy, którzy udzielają się przy skokach narciarskich (Stoch – 15%, Żyła, – 13%, Kot – 9%)
Aktywności pomiędzy stronami partii są odbiciem sceny politycznej:
1 2 3 4 5 6 7 8 9 |
interactions %>% filter(a_name != b_name) %>% filter(a_type == "partia", b_type == "partia") %>% ggplot() + geom_tile(aes(a_name, b_name, fill=100*percent), color="lightgray") + scale_fill_gradient(low="lightgreen", high="darkgreen") + labs(y="Aktywni na stronie...", x="...są też aktywni na stronie", fill="Procent\nużytkowników\nwchodzących\nw interakcje\nna fanpage") + theme(axis.text.x = element_text(angle=90, hjust=1, vjust=0)) |
- z PiSem nikt nie chce gadać ;)
- “totalna opozycja” gotuje się we własnym sosie, PO i Nowoczesna udziela się na stronach KODu (na marszach też), a z kolei KOD udziela się na stronach Platformy (33.6%!)
- Korwin i Kukiz to kolejny wzajemny kociołek
- SLD ciśnie w KOD i PO
- Razem żyje we własnym świecie
Natomiast aktywności pomiędzy stronami “sportowymi” są również przewidywalne:
1 2 3 4 5 6 7 8 9 |
interactions %>% filter(a_name != b_name) %>% filter(a_type == "sport", b_type == "sport") %>% ggplot() + geom_tile(aes(a_name, b_name, fill=100*percent), color="lightgray") + scale_fill_gradient(low="lightgreen", high="darkgreen") + labs(y="Aktywni na stronie...", x="...są też aktywni na stronie", fill="Procent\nużytkowników\nwchodzących\nw interakcje\nna fanpage") + theme(axis.text.x = element_text(angle=90, hjust=1, vjust=0)) |
Znowu widać grupy “wzajemnej adoracji”: skoczkowie (ktoś aktywny u Maćka Kota jest też aktywny u Piotra Żyły i Kamila Stocha) oraz piłkarze (Piszczek, Milik, Błaszczykowski, Grosicki, Lewandowski).
Na koniec dochodzimy do zestawień przepływu aktywności partia – sport:
Zobaczmy top trzech stron w tabelce:
L.p. | Partia | Sport | Procent |
---|---|---|---|
1 | Janusz Korwin-Mikke | Robert Lewandowski | 17.4 |
2 | Janusz Korwin-Mikke | Piotr Żyła- Official | 16.6 |
3 | Janusz Korwin-Mikke | Kuba Błaszczykowski | 15.2 |
1 | Komitet Obrony Demokracji | Robert Lewandowski | 14.5 |
2 | Komitet Obrony Demokracji | Kamil Stoch – Oficjalna strona | 14.5 |
3 | Komitet Obrony Demokracji | Kuba Błaszczykowski | 11.3 |
1 | Kukiz ’15 | Kamil Stoch – Oficjalna strona | 15.6 |
2 | Kukiz ’15 | Piotr Żyła- Official | 15.0 |
3 | Kukiz ’15 | Robert Lewandowski | 14.9 |
1 | Nowoczesna | Robert Lewandowski | 16.8 |
2 | Nowoczesna | Kamil Stoch – Oficjalna strona | 13.6 |
3 | Nowoczesna | Kuba Błaszczykowski | 12.4 |
1 | Platforma Obywatelska | Robert Lewandowski | 17.0 |
2 | Platforma Obywatelska | Kamil Stoch – Oficjalna strona | 14.8 |
3 | Platforma Obywatelska | Kuba Błaszczykowski | 12.4 |
1 | Polskie Stronnictwo Ludowe | Robert Lewandowski | 15.3 |
2 | Polskie Stronnictwo Ludowe | Kamil Stoch – Oficjalna strona | 14.1 |
3 | Polskie Stronnictwo Ludowe | Piotr Żyła- Official | 11.6 |
1 | Prawo i Sprawiedliwość | Kamil Stoch – Oficjalna strona | 22.3 |
2 | Prawo i Sprawiedliwość | Robert Lewandowski | 19.1 |
3 | Prawo i Sprawiedliwość | Kuba Błaszczykowski | 17.4 |
1 | Razem | Kamil Stoch – Oficjalna strona | 6.2 |
2 | Razem | Robert Lewandowski | 5.4 |
3 | Razem | Piotr Żyła- Official | 5.2 |
1 | Sojusz Lewicy Demokratycznej | Kamil Stoch – Oficjalna strona | 18.6 |
2 | Sojusz Lewicy Demokratycznej | Robert Lewandowski | 14.1 |
3 | Sojusz Lewicy Demokratycznej | Piotr Żyła- Official | 12.5 |
Widać, że niezależnie od sympatii politycznych lubimy gwiazdy polskiego sportu. Jeśli usuniemy te gwiazdy (Lewandowski, Błaszczykowski, Stoch) oraz dodatkowo Żyłę i Milika zostanie nam:
L.p. | Partia | Sport | Procent |
---|---|---|---|
1 | Janusz Korwin-Mikke | Michał Pazdan | 12.0 |
2 | Janusz Korwin-Mikke | Grzegorz Krychowiak | 10.6 |
3 | Janusz Korwin-Mikke | Agnieszka Radwanska | 8.2 |
1 | Komitet Obrony Demokracji | Agnieszka Radwanska | 9.5 |
2 | Komitet Obrony Demokracji | Justyna Kowalczyk – oficjalna strona | 6.9 |
3 | Komitet Obrony Demokracji | Maciej Kot | 5.3 |
1 | Kukiz ’15 | Agnieszka Radwanska | 9.5 |
2 | Kukiz ’15 | Michał Pazdan | 8.9 |
3 | Kukiz ’15 | Grzegorz Krychowiak | 8.3 |
1 | Nowoczesna | Agnieszka Radwanska | 10.3 |
2 | Nowoczesna | Grzegorz Krychowiak | 6.4 |
3 | Nowoczesna | Michał Pazdan | 6.3 |
1 | Platforma Obywatelska | Agnieszka Radwanska | 9.1 |
2 | Platforma Obywatelska | Grzegorz Krychowiak | 6.1 |
3 | Platforma Obywatelska | Maciej Kot | 5.7 |
1 | Polskie Stronnictwo Ludowe | Maciej Kot | 7.0 |
2 | Polskie Stronnictwo Ludowe | Agnieszka Radwanska | 6.6 |
3 | Polskie Stronnictwo Ludowe | Grzegorz Krychowiak | 6.6 |
1 | Prawo i Sprawiedliwość | Agnieszka Radwanska | 16.5 |
2 | Prawo i Sprawiedliwość | Maciej Kot | 9.9 |
3 | Prawo i Sprawiedliwość | Michał Pazdan | 9.5 |
1 | Razem | Agnieszka Radwanska | 3.7 |
2 | Razem | Grzegorz Krychowiak | 2.6 |
3 | Razem | Michał Pazdan | 2.6 |
1 | Sojusz Lewicy Demokratycznej | Agnieszka Radwanska | 8.7 |
2 | Sojusz Lewicy Demokratycznej | Maciej Kot | 7.9 |
3 | Sojusz Lewicy Demokratycznej | Justyna Kowalczyk – oficjalna strona | 6.1 |
Tutaj już widać różnice. Dominuje piłka nożna i międzynarodowa gwiazda – Agnieszka Radwańska. Ale można bardzo uprościć ogląd i wyciągnąć wnioski:
- fani Korwina lubią piłkę nożną (jak bodaj 4/7 planety)
- fani KOD – kibicują kobietom, szczególnie Radwańskiej
- Kukiz też raczej jest po stronie piłki nożnej, ale docenia tenis
- Nowoczesna wiele nie odbiega od PO – w obu partiach oprócz piłki ceni się Agę
- PSL lubi to co jest na topie w danym momencie i po prostu gratulują zwycięzcom
- w PiSie zaskoczenie – Radwańska (tuż po wyjętej wcześniej piłce i skokach)
- Razem wpisuje się w sympatie podobnie do Nowoczesnej
- zaś SLD podobnie do KODu
Zobaczmy na koniec “aktywiści” której partii są najbardziej aktywni na stronach sportowych (czyli w drugą stronę):
Sport | Partia | Procent |
---|---|---|
Agnieszka Radwanska | Prawo i Sprawiedliwość | 16.5 |
Arek Milik | Janusz Korwin-Mikke | 12.5 |
Artur Szpilka | Janusz Korwin-Mikke | 5.9 |
Ekstraklasa Trolls | Janusz Korwin-Mikke | 7.0 |
Ewa Chodakowska | Prawo i Sprawiedliwość | 3.9 |
FANGOL.pl | Janusz Korwin-Mikke | 2.1 |
fit.pl | Komitet Obrony Demokracji | 0.2 |
Grzegorz Krychowiak | Janusz Korwin-Mikke | 10.6 |
Joanna Jedrzejczyk | Janusz Korwin-Mikke | 7.1 |
Justyna Kowalczyk – oficjalna strona | Komitet Obrony Demokracji | 6.9 |
Kamil Glik | Janusz Korwin-Mikke | 2.4 |
Kamil Grosicki | Janusz Korwin-Mikke | 8.0 |
Kamil Stoch – Oficjalna strona | Prawo i Sprawiedliwość | 22.3 |
Kocham Football | Janusz Korwin-Mikke | 5.0 |
Kuba Błaszczykowski | Prawo i Sprawiedliwość | 17.4 |
Lech Poznań | Sojusz Lewicy Demokratycznej | 1.6 |
Łączy nas piłka | Nowoczesna | 1.6 |
Łukasz Piszczek | Janusz Korwin-Mikke | 5.6 |
Maciej Kot | Prawo i Sprawiedliwość | 9.9 |
Mamed Khalidov | Janusz Korwin-Mikke | 5.2 |
Michał Pazdan | Janusz Korwin-Mikke | 12.0 |
Official Robert Burneika | Janusz Korwin-Mikke | 6.1 |
Onet Sport | Nowoczesna | 0.9 |
Piotr Żyła- Official | Janusz Korwin-Mikke | 16.6 |
Poznań Maraton | Sojusz Lewicy Demokratycznej | 0.4 |
Przegląd Sportowy | Janusz Korwin-Mikke | 2.7 |
Robert Lewandowski | Prawo i Sprawiedliwość | 19.1 |
Rowerowe Porady | Kukiz ’15 | 0.5 |
Sport.pl | Janusz Korwin-Mikke | 1.5 |
SportoweFakty.pl | Sojusz Lewicy Demokratycznej | 1.7 |
- najbardziej “fit” chce być PiS (najwięcej współakcji ze stroną Ewy Chodakowskiej)
- “Siła!” i Robert “Hardkorowy koksu” Burneika najwięcej zwolenników ma po stronie Korwina, identycznie jak Artur Szpilka czy Mamed Khalidov lub Joanna Jędrzejczyk. Mocne sporty lubią jak widać właśnie Korwiniści
- “Porady rowerowe” najbardziej (chociaż i tak niewiele) interesują aktywnych na stronach Kukiza oraz Razem (różnica na poziomie setnych punktu procentowego)
Jeśli zaś chodzi o media: SportoweFakty.pl czyta SLD, Sport.pl oraz Przegląd Sportowy – Korwin, Onet Sport – Nowoczesna.
Znaleźliście jeszcze coś ciekawego w tych danych? Dajcie znać w komentarzach!
Jak uzyskać te tokeny?
fb_app_id = „xxxx”
fb_app_secret = „yyyy”
Trzeba założyć sobie aplikację na Facebooku – use the Google, Luke! ;)
Pingback: Najbardziej aktywni na stronach partii | Łukasz Prokulski
Długo trwało uwierzytelnianie w przeglądarce??
> library(httr)
> library(Rfacebook)
> library(tidyverse)
> fb_app_id = „798600240344717”
> fb_app_secret = „baf6683b751cc9544e19fffff186bad4”
> fb_oauth <- fbOAuth(app_id = fb_app_id, app_secret = fb_app_secret)
Copy and paste into Site URL on Facebook App Settings: http://localhost:1410/
When done, press any key to continue…fb_oauth <- fbOAuth(app_id = fb_app_id, app_secret = fb_app_secret)
Waiting for authentication in browser…
Press Esc/Ctrl + C to abort
Uruchamiasz to na serwerze jakimś czy na lokalnej maszynie? W pierwszym przypadku może być problem (bo serwer nie może otworzyć dla Ciebie przeglądarki gdzie trzeba kliknąć).
Obejściem jest uruchomienie tego lokalnie, po autentykacji zapisanie zmiennej fb_oauth do pliku i skopiowanie tego pliku na serwer. A na serwerze w kodzie zamiast się autoryzować na nowo wczytujesz zapisany plik.
No chyba, że Facebook coś pozmieniał…