Memahami Dinamika Twitter Dengan R dan Gephi: Analisis dan Sentralitas Teks

Diterbitkan: 2022-07-22

Artikel ini memperluas dan memperdalam analisis yang disajikan dalam angsuran pertama dari seri analisis jaringan sosial kami. Kami menggunakan dataset Twitter dan jaringan interaksi yang sama yang dibangun di artikel pertama. Namun, kali ini, idenya adalah untuk menyimpulkan aktor utama dengan lebih baik, mengidentifikasi topik diskusi mereka, dan memahami bagaimana topik ini menyebar.

Sentralitas Jaringan Sosial

Untuk mencapai tujuan kita, pertama-tama kita perlu memperkenalkan konsep sentralitas . Dalam ilmu jaringan, sentralitas mengacu pada node yang memiliki pengaruh kuat pada jaringan. Pengaruh adalah konsep yang ambigu; itu bisa dipahami dengan banyak cara. Apakah node dengan banyak edge lebih berpengaruh daripada node dengan edge yang lebih sedikit tetapi lebih "penting"? Apa yang merupakan keunggulan penting di jejaring sosial?

Untuk mengatasi ambiguitas ini, para ilmuwan jaringan telah mengembangkan banyak ukuran sentralitas. Di sini, kita membahas empat ukuran yang umum digunakan, meskipun banyak lagi yang tersedia.

Derajat

Ukuran yang paling umum dan intuitif adalah sentralitas derajat. Gagasan di balik sentralitas derajat sederhana: Ukur pengaruh dengan derajat simpul. Ini dapat memiliki varian jika grafik diarahkan; dalam hal ini, Anda dapat mengukur derajat masuk dan derajat keluar—yang pertama dikenal sebagai skor hub dan yang kedua sebagai skor otoritas.

Dalam angsuran pertama dari seri ini, kami menggunakan pendekatan tidak terarah. Kali ini, kami fokus pada pendekatan indegree. Ini memungkinkan analisis yang lebih akurat dengan menekankan pengguna yang di-retweet oleh orang lain daripada pengguna yang hanya sering me-retweet.

vektor eigen

Ukuran vektor eigen dibangun di atas sentralitas derajat. Semakin banyak simpul yang berpengaruh menunjuk ke simpul tertentu, semakin tinggi skornya. Kita mulai dengan matriks adjacency , di mana baris dan kolom mewakili node, dan kita menggunakan 1 atau 0 untuk menunjukkan apakah node yang sesuai dari baris dan kolom tertentu terhubung. Perhitungan utama memperkirakan vektor eigen matriks. Vektor eigen utama akan berisi ukuran sentralitas yang kita inginkan, di mana posisi i akan menampung skor sentralitas dari simpul i .

Peringkat halaman

PageRank adalah variasi ukuran vektor eigen di inti Google. Metode pasti yang digunakan Google tidak diketahui, tetapi ide umumnya adalah bahwa setiap node dimulai dengan skor 1, kemudian mendistribusikan skornya di bagian yang sama ke setiap tepinya. Misalnya, jika sebuah simpul memiliki tiga tepi yang memanjang darinya, ia "mengirim" sepertiga dari skornya melalui setiap tepi. Pada saat yang sama, simpul dibuat lebih penting oleh tepi yang mengarah ke sana. Ini menghasilkan sistem persamaan N yang dapat dipecahkan dengan N tidak diketahui.

Antara

Ukuran keempat, betweenness , menggunakan pendekatan yang sangat berbeda. Di sini, sebuah node dikatakan berpengaruh jika termasuk dalam banyak jalur pendek antara node lainnya. Artinya, ia bertanggung jawab untuk berkomunikasi dengan banyak node lain, menghubungkan "dunia yang berbeda."

Misalnya, dalam analisis jejaring sosial, simpul semacam ini dapat dipahami sebagai tipe orang yang membantu orang lain menemukan pekerjaan baru atau membuat koneksi baru—mereka adalah pintu ke lingkaran sosial yang sebelumnya tidak dikenal.

Mana yang Harus Saya Gunakan?

Ukuran sentralitas yang tepat tergantung pada tujuan analisis Anda. Apakah Anda ingin tahu pengguna mana yang sering dipilih oleh orang lain dalam hal kuantitas? Sentralitas gelar kemungkinan akan menjadi pilihan terbaik Anda. Atau apakah Anda lebih suka ukuran sentralitas yang mempertimbangkan kualitas? Dalam hal ini, eigenvector atau PageRank akan memberikan hasil yang lebih baik. Jika Anda ingin mengetahui pengguna mana yang berfungsi paling efektif sebagai jembatan antara komunitas yang berbeda, keberantaraan adalah pilihan terbaik Anda.

Saat menggunakan beberapa ukuran serupa, misalnya, vektor eigen dan PageRank, Anda dapat memperkirakan semuanya dan melihat apakah mereka menghasilkan peringkat yang setara. Jika tidak, Anda dapat memperdalam analisis Anda tentang perbedaan atau menghasilkan ukuran baru dengan menggabungkan skor mereka.

Pendekatan lain menggunakan analisis komponen utama untuk memperkirakan ukuran mana yang memberi Anda lebih banyak informasi tentang pengaruh nyata dari node pada jaringan Anda.

Perhitungan Sentralitas Langsung

Mari kita lihat bagaimana kita dapat menghitung ukuran ini menggunakan R dan RStudio. (Mereka juga dapat dilakukan dengan Gephi.)

Pertama, kita perlu memuat semua perpustakaan yang akan kita gunakan di seluruh artikel ini:

 library("plyr") library(igraph) library(tidyverse) library(NLP) library("tm") library(RColorBrewer) library(wordcloud) library(topicmodels) library(SnowballC) library("textmineR")

Selanjutnya, kami akan menghapus node terisolasi dari data yang kami gunakan sebelumnya, karena tidak berguna untuk analisis ini. Kemudian, kita akan menggunakan fungsi igraph betweenness , centr_eigen , page_rank , dan degree untuk memperkirakan ukuran sentralitas. Terakhir, kami akan menyimpan skor pada objek igraph dan pada bingkai data untuk melihat pengguna mana yang paling sentral.

 load("art1_tweets.RData") Isolated = which(degree(net)==0) net_clean = delete.vertices(net, Isolated) cent<-data.frame(bet=betweenness(net_clean),eig=centr_eigen(net_clean)$vector,prank=(page_rank(net_clean)$vector),degr=degree(net_clean, mode="in")) cent <- cbind(account = rownames(cent), cent)

Sekarang kita dapat memeriksa 10 pengguna paling sentral dengan setiap ukuran:

Derajat
 top_n(cent, 10 ,degr)%>% arrange(desc(degr))%>% select(degr)
vektor eigen
 top_n(cent, 10 ,eig)%>% arrange(desc(eig))%>% select(eig)
Peringkat halaman
 top_n(cent, 10 ,prank)%>% arrange(desc(prank))%>% select(prank)
Antara
 top_n(cent, 10 ,bet)%>% arrange(desc(bet))%>% select(bet)

Hasil:

Derajat vektor eigen Peringkat halaman Antara
ESPNFC 5892 PSG_inside 1 mundodabola 0,037 pemandangan 77704
TrollSepakbola 5755 CrewsMat19 0,51 AleLiparoti 0,026 EdmundOris 76425
PSG_inside 5194 eh01195991 0.4 PSG_inside 0,017 ba******l 63799
CrewsMat19 4344 mohammad135680 0.37 Roy Nemer 0,016 Francisco Gaius 63081
sepak bola 4054 ActuFoot_ 0.34 TrollSepakbola 0,013 Yemihazan 62534
PSG_espanol 3616 marttvall 0.34 ESPNFC 0,01 tagar2weet 61123
IbaiOut 3258 ESPNFC 0,3 PSG_espanol 0,007 Angela_FCB 60991
ActuFoot_ 3175 sepak bola 0,25 Kaki Instan 0,007 Zyyon_ 57269
FootyHumor 2976 SaylorBulanTentara 0,22 IbaiOut 0,006 CrewsMat19 53758
mundodabola 2778 JohnsvillPat 0.2 2010MisterChip 0,006 MdeenOlawale 49572

Kita dapat melihat bahwa tiga langkah pertama berbagi sejumlah pengguna, seperti PSG_inside, ESPNFC, CrewsMat19, dan TrollFootball. Kita dapat berasumsi bahwa mereka memiliki pengaruh yang kuat atas diskusi. Antara memiliki pendekatan yang berbeda untuk mengukur sentralitas dan karena itu tidak menunjukkan banyak tumpang tindih dengan teknik lainnya.

Catatan: Pandangan yang diungkapkan oleh akun Twitter yang disebutkan dalam artikel ini tidak mencerminkan pandangan Toptal atau penulisnya.

Pada gambar berikut, Anda dapat melihat grafik jaringan berwarna asli kami dengan dua lapisan label pengguna. Yang pertama, node disorot oleh skor PageRank mereka, dan yang kedua, dengan skor antara mereka:

Gambar yang menunjukkan plot PageRank berwarna, dengan 10 pengguna teratas dan jaringan mereka disorot. Tiga pengguna terbesar adalah PSG_inside, TrollFootball, dan ESPNFC. ESPNFC terletak di sebelah kiri plot dan berwarna ungu, sedangkan PSG_inside ditempatkan di sebelah kanannya, berwarna merah. TrollFootball terletak lebih tinggi dan di sebelah kanannya, di antara pengguna berwarna hijau, biru, dan oranye.
Diskusi Messi dengan 10 pengguna PageRank teratas disorot

Gambar yang menunjukkan plot perbedaan warna, dengan 10 pengguna teratas dan jaringan mereka diberi label dan disorot. Semua dari 10 pengguna teratas, yang ukurannya lebih mirip dari pada gambar sebelumnya, terletak di sudut kiri bawah gambar, yang berwarna ungu. Mereka dikelompokkan bersama dengan erat.
Diskusi Messi dengan 10 besar pengguna antara yang disorot

Gephi dapat digunakan untuk mereproduksi gambar-gambar ini. Anda dapat memperkirakan skor antara atau PageRank menggunakan tombol Diameter Jaringan di panel statistik. Kemudian, Anda dapat menampilkan nama node menggunakan atribut seperti yang ditunjukkan pada angsuran pertama dalam seri ini.

Analisis Teks: R dan LDA

Kami juga dapat menganalisis diskusi jejaring sosial untuk mengidentifikasi apa yang dibicarakan pengguna. Ada beberapa cara untuk mendekati ini. Kami akan melakukan pemodelan topik melalui Latent Dirichlet Allocation (LDA), sebuah teknik pembelajaran mesin tanpa pengawasan yang memungkinkan kami memperkirakan kumpulan kata mana yang cenderung muncul bersamaan. Kemudian, melalui rangkaian kata tersebut, kita dapat menyimpulkan topik yang sedang dibahas.

Langkah pertama adalah membersihkan teks. Untuk melakukan itu, kita mendefinisikan fungsi berikut:

 # This function normalizes text by removing Twitter-related terms and noisy characters sanitize_text <- function(text) { # Convert to ASCII to remove accented characters: text <- iconv(text, to = "ASCII", sub = " ") # Move to lower case and delete RT word (this is added by Twitter) text <- gsub("rt", " ", tolower(text)) # Delete links and user names: text <- gsub("@\\w+", " ", gsub("http.+ |http.+$", " ", text)) # Delete tabs and punctuation: text <- gsub("[ |\t]{2,}", " ", gsub("[[:punct:]]", " ", text)) text <- gsub("amp", " ", text) # Remove HTML special character # Delete leading and lagging blanks: text <- gsub("^ ", "", gsub(" $", "", text)) text <- gsub(" +", " ", text) # Delete extra spaces return(text) }

Kita juga perlu menghapus stopword, duplikat, dan entri kosong. Selanjutnya, kita harus mengonversi teks kita menjadi matriks istilah dokumen untuk diproses oleh LDA.

Dalam kumpulan data ini, kami memiliki pengguna yang berbicara dalam banyak bahasa (Inggris, Spanyol, Prancis, dll.). LDA bekerja paling baik jika kita fokus pada satu bahasa. Kami akan menerapkannya pada pengguna komunitas terbesar yang terdeteksi dalam angsuran pertama seri ini, yang sebagian besar terdiri dari akun dengan pengguna berbahasa Inggris.

 # Detect communities: my.com.fast <-cluster_louvain(as.undirected(simplify(net))) largestCommunities <- order(sizes(my.com.fast), decreasing=TRUE)[1:3] # Save the usernames of the biggest community: community1 <- names(which(membership(my.com.fast) == largestCommunities[1])) # Sanitize the text of the users of the biggest community: text <- unique(sanitize_text(tweets.df[which(tweets.df$screen_name %in% community1),]$text)) text = text[text!=''] # Delete empty entries stopwords_regex = paste(stopwords('es'), collapse = '\\b|\\b') stopwords_regex = paste0('\\b', stopwords_regex, '\\b') # Remove English stopwords: text = stringr::str_replace_all(text, stopwords_regex, '') # Create the document term matrix: dtm <- CreateDtm(text, doc_names = seq(1:length(text)), ngram_window = c(1, 2))

Jumlah Topik dan Skor Koherensi

Hyperparameter utama yang perlu kita definisikan di LDA adalah jumlah (k) topik yang ingin kita perkirakan. Namun, bagaimana kita bisa mengetahuinya sebelumnya? Salah satu pendekatan umum adalah melatih model LDA pada nilai k yang berbeda dan mengukur koherensi masing-masing. Kami akan melakukan ini untuk nilai k dari 3 hingga 20, karena nilai di luar rentang ini tidak layak untuk diperiksa, menurut pengalaman saya:

 tf <- TermDocFreq(dtm = dtm) # Remove infrequent words: tf_trimmed = tf$term[ tf$term_freq > 1 & tf$doc_freq < nrow(dtm) / 2 ] # Create a folder to store trained models: model_dir <- paste0("models_", digest::digest(tf_trimmed, algo = "sha1")) if (!dir.exists(model_dir)) dir.create(model_dir) # Define a function to infer LDA topics: train_lda_model <- function(number_of_topics){ filename = file.path(model_dir, paste0(number_of_topics, "_topics.rda")) # Check if the model already exists: if (!file.exists(filename)) { # To get exactly the same output on each run, use a constant seed: set.seed(12345) lda_model = FitLdaModel(dtm = dtm, k = number_of_topics, iterations = 500) lda_model$k = number_of_topics lda_model$coherence = CalcProbCoherence(phi = lda_model$phi, dtm = dtm, M = 5) save(lda_model, file = filename) } else { load(filename) } lda_model } # The number of topics that we are going to infer in each LDA training run: topic_count = seq(3, 20, by = 1) # Train through the TmParallelApply function models = TmParallelApply(X = topic_count, FUN = train_lda_model, export = c("dtm", "model_dir"))

Selanjutnya, kami membuat grafik nilai koherensi masing-masing:

 coherence_by_topics_quantity = data.frame( topic_number = sapply(models, function(model_instance) nrow(model_instance$phi)), score_coherence = sapply(models, function(model_instance) mean(model_instance$coherence)), stringsAsFactors = FALSE) ggplot(coherence_by_topics_quantity, aes(x = topic_number, y = score_coherence)) + geom_point() + geom_line(group = 1) + ggtitle("Coherence by Topic") + theme_minimal() + scale_x_continuous(breaks = seq(1,20,1)) + ylab("Coherence Score") + xlab("Number of topics")

Nilai koherensi yang tinggi menunjukkan segmentasi teks yang lebih baik ke dalam topik:

Grafik yang menunjukkan skor koherensi untuk berbagai topik. Skor koherensi bervariasi dari sedikit di atas 0,05 pada enam hingga tujuh topik, dengan tiga hingga 12 topik semuanya memiliki skor di bawah 0,065. Skor tiba-tiba memuncak sekitar 0,105 untuk 13 topik. Kemudian turun di bawah 0,06 untuk 17 topik, naik hampir 0,09 untuk 19 topik, dan berakhir tepat di atas 0,07 untuk 20 topik.

Kami mencapai skor koherensi puncak kami dengan k = 13, jadi kami akan menggunakan model LDA yang dilatih dengan 13 topik. Melalui fungsi GetTopTerms, kita dapat melihat 10 kata utama untuk setiap topik dan memperkirakan semantik topik melalui mereka:

 best_model <- models[which.max(coherence_by_topics_quantity$score_coherence)][[ 1 ]] # Most important terms by topic: best_model$top_terms <- GetTopTerms(phi = best_model$phi, M = 20) top10 <- as.data.frame(best_model$top_terms) top10

Tabel berikut merinci lima topik terpenting yang terdeteksi dan 10 kata utama yang menunjukkannya:

t_1 t_2 t_3 t_4 t_5
1 messi messi messi messi messi
2 singa Instagram liga Est psg
3 Lionel Messi pos menang aku Leo
4 psg juta sasaran au leo_messi
5 Madrid suka ch menuangkan ahora
6 nyata spo ion pas teman
7 barcelona kambing ch_ion avec va
8 Paris psg ucl du ser
9 Real Madrid batang balon qui jugador
10 mbap lebih besar dunia ya besar

Meskipun sebagian besar pengguna di komunitas ini adalah penutur bahasa Inggris, masih ada sejumlah penutur bahasa Prancis dan Spanyol (t_4 dan t_5 dalam tabel). Dapat kita simpulkan bahwa topik pertama berkaitan dengan tim Messi sebelumnya (FC Barcelona), topik kedua tentang postingan Messi di Instagram, dan topik ketiga berfokus pada pencapaian Messi.

Sekarang setelah kita memiliki topik, kita dapat memprediksi topik mana yang paling banyak dibahas. Untuk melakukan itu, pertama-tama kami akan menggabungkan tweet oleh pengguna (sekali lagi, dari komunitas terbesar):

 tweets.df.com1 = tweets.df[which(tweets.df$screen_name %in% community1),] users_text <- ddply(tweets.df.com1, ~screen_name, summarise, text = paste(text, collapse = " "))

Kemudian, kami membersihkan teks seperti sebelumnya dan membuat DTM. Setelah itu, kami memanggil fungsi predict menggunakan model LDA kami dan DTM sebagai argumen. Selain itu, kami menetapkan metode ke Gibbs untuk meningkatkan waktu komputasi karena kami memiliki banyak teks untuk dianalisis:

 users_text$text <- sanitize_text(users_text$text) # Get rid of duplicates stopwords_regex = paste(stopwords('en'), collapse = '\\b|\\b') stopwords_regex = paste0('\\b', stopwords_regex, '\\b') users_text$text = stringr::str_replace_all(users_text$text, stopwords_regex, '') dtm.users.com1 <- CreateDtm(users_text$text, doc_names = users_text$screen_name, ngram_window = c(1, 2)) com1.users.topics = predict(best_model, dtm.users.com1, method="gibbs", iterations=100)

Sekarang, dalam bingkai data com1.users.topics , kita melihat seberapa banyak setiap pengguna berbicara tentang setiap topik:

Akun t_1 t_2 t_3 t_4 t_5 […]
___99 0,02716049 0.86666666 0,00246913 0,00246913 0,00246913
Bos__ 0,05185185 0.84197530 0,00246913 0,00246913 0,00246913
Memphis 0,00327868 0,00327868 0,03606557 0,00327868 0,00327868
___Alex1 0,00952380 0,00952380 0,00952380 0,00952380 0,00952380
[…]

Akhirnya, dengan informasi ini, kita dapat membuat atribut baru pada grafik simpul untuk menentukan topik mana yang paling banyak dibicarakan oleh pengguna mana. Kemudian kita dapat membuat file GML baru untuk memvisualisasikannya di Gephi:

 # Get the subgraph of the first community: net.com1 = induced_subgraph(net,community1) # Estimate the topic with the max score for each user: com1.users.maxtopic = cbind(users_text$screen_name, colnames(com1.users.topics)[apply(com1.users.topics, 1, which.max)]) # Order the users topic data frame by the users' order in the graph: com1.users.maxtopic = com1.users.maxtopic[match(V(net.com1)$name, com1.users.maxtopic[,1]),] # Create a new attr of the graph by the topic most discussed by each user: V(net.com1)$topic = com1.users.maxtopic[,2] # Create a new graph: write_graph(simplify(net.com1), "messi_graph_topics.gml", format = "gml") 

Grafik simpul berwarna yang dihasilkan menggunakan Gephi, menunjukkan ESPNFC sebagai pengguna dengan peringkat tertinggi berdasarkan sentralitas PageRank. ESPNFC terletak di dekat bagian bawah gambar, dengan banyak simpul ungu dikelompokkan di bawahnya.
Komunitas diskusi Messi terbesar yang diwarnai oleh topik dan dengan pengguna disorot oleh sentralitas PageRank

Gambar yang menunjukkan persentase pengguna yang disorot oleh setiap warna yang digunakan dalam grafik, dengan "t 6" ungu sebagai warna yang paling sering digunakan (40,53% dari semua pengguna dalam grafik), diikuti oleh "t 13" hijau pada 11,02 %, dan biru/sian "t 10" pada 9,68%. "NA" abu-abu di posisi kedua hingga terakhir dari daftar 11 ini, mencapai 2,25%.
Label topik dan persentase pengguna untuk setiap warna yang digunakan dalam grafik

Menyimpulkan Topik Penting dan Menerapkan Sentralitas Jaringan Sosial

Dalam angsuran pertama dari seri ini, kami belajar cara mendapatkan data dari Twitter, membuat grafik interaksi, memplotnya melalui Gephi, dan mendeteksi komunitas dan pengguna penting. Dalam angsuran ini, kami memperluas analisis ini dengan menunjukkan penggunaan kriteria tambahan untuk mendeteksi pengguna yang berpengaruh. Kami juga mendemonstrasikan cara mendeteksi dan menyimpulkan apa yang dibicarakan pengguna dan merencanakannya di jaringan.

Dalam artikel kami berikutnya, kami akan terus memperdalam analisis ini dengan menunjukkan bagaimana pengguna dapat mendeteksi momok media sosial: robot spam dan troll.

Bacaan Lebih Lanjut di Blog Teknik Toptal:

  • Analisis Jaringan Sosial Menggunakan Power BI dan R: Panduan Visual Kustom