1 Preface

1.1 Pendahuluan

Manusia merupakan makhlus sosial dimana interaksi sosial merupakan salah satu kebutuhan utamanya. Saat ini ada banyak cara untuk melakukan interaksi sosial diantaranya dengan memanfaatkan media sosial. Media sosial merupakan tools untuk mempermudah manusia dalam berinterkasi dan berbagai informasi.

Melalui media sosial, manusia dapat berinterkasi dengan mudah dan cepat tanpa dibatasi dengan kondisi geografis, kita bisa berinteraksi dengan orang yang sangat jauh secara geografis dengan cepat. Interkasi yang terjadi melalui media sosial menghasilkan data yang bisa dianalisa untuk mengetahui interkasi yang terjadi antar pengguna. Salah satu bentuk analisa yang bisa digunakan adalah social network analysis.

Materi ini bertujuan memberikan pemahaman kepada peserta workshop terkait penggunaan konsep graph dalam menganalis interkasi yang terjadi di media sosial. Adapun setelah mempelajari materi ini peserta diharapkan dapat memahami kegunaan dan potensi social network analysis sesuai dengan proses bisnis yang ada di bidang industri yang dijalani oleh peserta.

1.2 Library dan Setup

Untuk dapat mengikuti materi ini, peserta diharapkan sudah menginstall beberapa packages di bawah ini. Apabila package tersebut belum terinstall, silahkan jalankan chunk atau baris kode berikut. Apabila sudah ter-install, lewati chunk berikut dan muat package yang dibutuhkan dengan menjalankan chunk selanjutnya.

# install.packages(c("tidyverse","rtweet", "tidygraph","ggraph","igraph", "knir", "rmarkdown"))
library(tidyverse)
library(rtweet)

# graph
library(tidygraph)
library(ggraph)
library(igraph)

1.3 Tujuan Pembelajaran

Tujuan utama dari workshop ini adalah untuk memberikan pengenalan yang komprehensif mengenai tools dan perangkat lunak yang digunakan untuk melakukan social network analysis, yakni sebuah open-source populer: R. Adapun materi ini akan mencakup:

  • Dasar Bahasa Pemrograman R
    • Introduction to R programming language.
    • Working with the RStudio environment.
    • Basic Control Statement in R.
    • Data manipulation and processing with R tidyverse.
  • Introduction to Social Network Analysis
    • Graph theory: nodes and edges
    • Graph theory: Directed and undirected graph
    • Graph metrics: Centrality
  • CASE STUDY: Information Activity Network
    • Data gathering using rtweet package (Twitter API)
    • Feature engineering
    • Build nodes, edges, and graph dataframe
    • Build communities and calculate metrics
    • Visualize network using tidygraph

2 Dasar Pemrograman di R

2.1 Import Data

Data yang digunakan pada workshop ini merupakan data yang dikumpulkan dari twitter dengan hashtag #COVID19, periode pengumpulan data dari 7 juni 2020 hingga 9 Juni 2020, data tersebut tersimpan pada folder data_input dengan nama tweets.csv. untuk membaca file tersebut bisa menggunakan fungsi read.csv() kemudian masukkan path dari file tersebut. Data yang sudah di baca akan tersimpan pada objek tweets.

tweets <- read.csv("data_input/tweets.csv") 
head(tweets, 10)

Fungsi head() digunakan untuk melihat beberapa (default 6) data pertama. dari hasil diatas bisa dilihat bahwa terdapat 90 kolom beberapa deskripsi dari kolom tersebut seperti berikut:
- user_id : id dari pengguna twitter
- status_id : id dari status yang dibuat
- created_at : waktu ketika status tersebut dibuat
- screen_name : nama pengguna twitter
- is_retweet : Jenis dari status tersebut apakah sebuah retweet atau bukan

untuk deskiripsi lengkap dari seluruh kolom dapat dilihat dari dokuentasi resmi twitter developer

2.2 Data Type and Structure

Kita sudah mempelajari bagaimana mengecek sample dari data, sekarang kita perlu mengetahui tipe data dari masing masing kolom yang ada. Kita bisa menggunakan fungsi str() untuk melihat struktur serta dimensi dari data.

tweets %>% 
  select(1:10) %>% 
  str()
#> 'data.frame':    35977 obs. of  10 variables:
#>  $ user_id             : num  306732346 211316225 211316225 19288705 19288705 ...
#>  $ status_id           : num  1269537593705877504 1269537593487765504 1269537466559746048 1269537592191651840 1269534927005065216 ...
#>  $ created_at          : chr  "2020-06-07 07:52:03" "2020-06-07 07:52:03" "2020-06-07 07:51:33" "2020-06-07 07:52:03" ...
#>  $ screen_name         : chr  "cesajid" "cranemtn" "cranemtn" "psigrist" ...
#>  $ text                : chr  "It’s my humble request to Overseas Ministry @mophrd :\nPlease make appropriate arrangements for receiving deadb"| __truncated__ "<U+0E2D><U+0E34><U+0E48><U+0E21> <U+0E2B><U+0E21><U+0E35> <U+0E01><U+0E31><U+0E1A> <U+0E2B><U+0E21><U+0E35><U+0"| __truncated__ "<U+0E02><U+0E2D><U+0E02><U+0E49><U+0E32><U+0E27><U+0E2A><U+0E27><U+0E22> 1 <U+0001F35A> <U+0E1B><U+0E39><U+0E1C"| __truncated__ "One third of the UK population suddenly has to discover blended learning, with home schooling part of the weekl"| __truncated__ ...
#>  $ source              : chr  "Twitter for Android" "Twitter for iPhone" "Twitter for iPhone" "Twitter for iPhone" ...
#>  $ display_text_width  : int  140 140 140 140 108 140 140 140 140 140 ...
#>  $ reply_to_status_id  : num  NA NA NA NA NA NA NA NA NA NA ...
#>  $ reply_to_user_id    : num  NA NA NA NA NA NA NA NA NA NA ...
#>  $ reply_to_screen_name: chr  NA NA NA NA ...

tweets merupakan sebuah ‘data.frame’ atau tabel dengan 35977 baris dan 90 kolom. Nama dari setiap kolom tertera disebelah kanan (user_id, status_id, dll). Teks chr, num menunjukkan tipe data dari masing - masing kolom.

2.3 Exploratory Data Analysis

Sebelum mebuat sebuah graph kita melakukan eksplorasi pada data yang ada. Kita bisa menghitung banyaknya data yang merupakan sebuah retweet atau bukan dengan menggunakan fungsi count().

tweets %>% 
  count(is_retweet)

dari hasil diatas bisa dilihat bahwa mayoritas data tweet yang ada merupakan sebuah retweet, oleh sebab itu mari kita lihat summary jadi jumlah retweet.

tweets %>% 
  filter(is_retweet) %>% 
  select(retweet_count) %>% 
  summary()
#>  retweet_count   
#>  Min.   :     0  
#>  1st Qu.:    10  
#>  Median :    62  
#>  Mean   :  1629  
#>  3rd Qu.:   481  
#>  Max.   :207549

Dari hasil diatas suatu tweet maksimal di retweet sebanyak 207549 kali, sedangkan apabila kita lihat secara nilai tengah (median) hanya 62. mari kita cari tau tweet apa yang memiliki jumlah retweet_count terbesar, dan apa isi dari tweet tersebut

3 Graph Theory

Dalam dunia matematika graph merupakan hubungan antar entitas, terdapat 2 komponen yang menyusun sebuah graph yaitu nodes/vertices yang merepresentasikan sebuah entitas dan edge/link menggambarkan sebuah hubungan. Dalam ilmu matematika cabang ilmu yang mempelajari graph disebut Graph Theory.

Bila kita hubungkan konsep graph kedalam interaksi sosial yang terjadi di twitter maka setiap node mewakili seorang user, sedangkan edge mewakili hubungan / interkasi yang terjadi (retweet, mention, quote).

3.1 Graph Directions

Secara umum hubungan antar nodes bisa dibagi menjadi 2 yaitu berarah (directed) dan tak berarah (undirected)

Graph berarah (directed graph) memiliki arah hubungan pada edge-nya hal ini ditandai dengan arah panah pada suatu graph. bila dilihat dari arah panahnya kita bisa membaginya menjadi 2 jenis yaitu in-degree dan out-degree. In-degree merepresentasikan jumlah edge yang menuju suatu node, sedangkan out-degree menunjukkan jumlah edge yang keluar dari suatu node.

Graph tak berarah (undirected graph) tidak menampilkan hubungan antar nodesnya, sehingga hubungan antar nodes dapat dilihat 2 arah. Undirected graph ditunjukkan dengan tidak adalanya panah pada suatu graph.

Dalam menentukan direction diperlukan pemahaman user kepada data yang digunakan, Sebagai contoh pada data twitter kita bisa melihat seseorang melakukan mention pada user lain ketika membuat sebuah tweet, interaksi tersebut dapat kita asumsikan sebagai directed graph karena kita tidak mengetahui respon dari pengguna yang di mention.

dibawah ini merupakan sample data antara user dengan user yang di-mention

tweets %>% 
  select(screen_name, mentions_screen_name) %>% 
  head()

3.2 Centrality Analysis

Centrality merupakan salah satu ukuran penting ketika melakukan analisa pada suatu graph. Melalui centrality kita dapat mengetahui “key player” atau node yang paling berpengaruh dari suatu graph. Ada berbagai macam cara untuk mengetahui “key player” dari sebuah graph, dimana tiap cara memiliki definisinya sendiri dalam menentukan node yang paling penting.

3.2.1 Degree Centrality

Degree centrality merupakan ukuran pemusatan yang menghitung banyaknya edges yang terhubung ke suatu node. Degree centrality dapat memberitahu seberapa banyak hubungan langsung yang dimiliki setiap node sehingga ketika kita ingin mencari individu yang memiliki koneksi langsung terbanayak dengan orang lain (orang paling populer) kita bisa melihat metrics ini.

Metrics ini cukup sederhana dalam proses perhitungannya sebagai contoh graph dibawah ini terdiri dari 6 nodes. Informasi keterhubungan antar node dapat diubah kedalam sebuah matriks yang disebut matriks adjacent. Matriks adjacent merupakan matriks yang berukuran n x n dimana n merupakan banyaknya node, nilai 1 pada matrix merepresentasikan adanya hubungan langsung antar node sedangkan nilai 0 berarti tidak memiliki hubungan langsung.

Perhatikan node 1 pada graph diatas, node tersebut terhubung dengan node 2, 4, dan 6 secara langsung, sehingga nilai pada baris pertama kolom ke 2,4, dan 6 berisi 1 sedangkan yang lainnya adalah 0. setelah membuat matriks adjacent, kita bisa menjumlahkan semua nilai tersebut, semakin besar nilai total maka semakin “populer” node tersebut.

Untuk menormalisasi nilai degree, nilai total dapat dibagi dengan jumlah node dikurang satu (n-1) sehingga range dari degree centrality berkisar 0 hingga 1. Semakin mendekati 1 maka node tersebut semakin banyak terhubung dengan node lain secara langsung.

3.2.2 Closeness Centrality

Berbeda dengan degree centrality yang mengukur seberapa “populer” suatu node, closeness centrality mengukur seberapa “dekat” suatu node dengan node lainnya. Closeness centrality dapat memberitahu kita node mana yang memiliki jarak terpendek keseluruh nodes. Ukuran ini dapat digunakan ketika kita ingin mencari tau individu yang paling efektif dalam persebaran informasi “broadcaster”.

Dalam proses perhitungannya kita perlu mengubah graph dimiliki kedalam matriks jarak (distance matrix). Distanace matrix menunjukkan banyaknya step yang dibutuhkan dari satu node ke node lainnya. Sebagai contoh jarak terdekat dari node 2 ke node 5 adalah 3, berarti butuh 3 steps untuk sampai dari node 2 ke node 5 (2 -> 3 -> 6 -> 5 atau 2 -> 1 -> 6 -> 5). Perhitungan jarak dilakukan kesemua kombinasi node yang ada kemudian dihitung total jaraknya. Semakin kecil total jarak berarti semakin dekat node tersebut dengan node lain.

agar range dari closeness centrality sama dengan yang lain (0 hingga 1) dan memiliki interpretasi yang sama (semakin mendekati 1 sekain baik) maka dapat dinormalisasikan dengan cara jumlah nodes dikurang 1 dibagi total distance (n-1)/total.

3.2.3 Betweenness Centrality

Betweenness centrality mengukur seberapa sering suatu node dilewati pada jalur terpendek antar nodes. Nilai ini dapat memberitahu node mana yang bisa digunakan sebagai “jembatan” penghubung dalam suatu graph. Metrics ini bisa digunakan untuk mengetahui individu yang mempengaruhi “aliaran” informasi.

Proses perhitungan metrics ini sedikit lebih kompleks bila dibandingan 2 metrics sebelumnya, oleh sebab itu mari kita pahami langkah demi langkahnya

  1. Buat kombinasi connection antar node. Karena graph ini bersifat undirected sehingga hubungan antar node 1 dan node 2 sama dengan B ke A. Warna merah pada tahap kedua (lihat gambar) menandakan kombinasi tersebut tidak digunakan dikarenakan duplikat.

  2. Dari 6 buah node yang ada didapati 15 kemungkinan hubungan antar node (lihat tahap 3 pada gambar). Kombinasi hubungan tersebut dicari kemungkinan jalur terpendeknya. Sebagai contoh dari node 2 ke node 4 terdapat 2 jalur terdekat yaitu (2,3,4) dan (2,1,4). Jalur yang lebih panjang tidak akan diperhitungkan.

  3. Tiap node diberikan point apabila node tersebut dilalui

  4. Jumlahkan semua point untuk setiap node. Semakin besar total point yang didapat maka semakin sering node tersebut dilalui.

  5. Lakukan scaling dengan membagi total betweeness dengan \(((n-1)(n-2))/2\)

3.2.4 Eigenvector Centrality

Sama seperti degree centrality eigenvector centrality mengukur seberapa penting suatu node berdasarkan banyaknya edge yang ada, yang membedakannya adalah pada eigenvector centrality akan melihat konektivitas dari tetangga node itu juga. Sebagai contoh seseorang dengan 300 relatively unpopular followers akan memiliki nilai eigenvector centrality lebih rendah bila dibandingkan seseorang dengan 300 very popular followers (seperti elon mask). Penggunaan eigenvector centrality sama seperti degree centrality yaitu untuk mencari node paling “populer” hanya saja metrics ini melihat secara keseluruhan.

Untuk menghitung nilai eigenvector centrality kita bisa melakukan beberapa tahapan yaitu:
- Membuat matrix adjacent
- mencari eigen vector dari matrix tersebut
- Menggunakan eigen vector tersebut sebagai nilai centralitynya

3.3 Graph in R

Pada umumnya ketika melakukan analisa pada suatu graph struktur data yang digunakan merupakan sebuah matrix baik itu matrix adjensy, atau matrix jarak. Pengolahan data menggunakan format matrix menggunakan memori (RAM) yang sangat besar karena dimensi dari metrix tersebut berukuran n x n dimana n merupakan jumlah node. Selain itu untuk melakukan wrangling pada data matrix tidak semudah melakukannya apabila data berformat dataframe, oleh sebab itu struktur data yang digunakan pada analisa graph di R berformat tbl_graph.

tbl_grah merupakan struktur data yang terdiri dari 2 dataframe (nodes dan edge) beserta informasi informasi lainnya. Kelebihan dari menggunakan struktur data ini yaitu kita bisa menggunakan grammar dari tidyverse sebagai proses wrangling di graph.

# data edges
edges_sample <- data.frame(from = c("B", "A", "D", "B", "A", "A"),
                           to = c("D", "B", "C", "C", "E","C"))

head(edges_sample)
# data nodes
nodes_sample <- data.frame(name = unique(c(edges_sample$from, edges_sample$to)))

Terdapat 2 dataframe diatas yaitu edges_sample yang berisi hubungan antar nodes (from, to) dan nodes_sample yang berisi kumpulan nodes yang berada pada graph. Untuk membuat suatu graph kita bisa menggunakan fungsi tbl_graph() dari package tidygraph. Informasi nodes dan edges yang sudah dimiliki bisa dimasukkan kedalam fungsi, selain itu kita bisa mendefinisikan jenis arahnya (directed), gunakan FALSE bisa graph merupakan sebuah undirected graph.

# membuat graph dari 2 data frame
gf_sample <- 
  tbl_graph(nodes = nodes_sample, 
          edges = edges_sample, 
          directed = F)

# cek class dari object gf_sample
class(gf_sample)
#> [1] "tbl_graph" "igraph"

Untuk memvisualisasikan data dalam sebuah plot sederhana bisa menggunakan fungsi plot(). Dari sini terlihat hubungan antar nodes yang ada pada data nodes_sample sebelumnya

# visualisasi sederhana
set.seed(100)
plot(x = gf_sample)

Kelebihan dari penggunaan format data tbl_graph yaitu kita dapat menggunakan fungsi- fungsi yang ada pada tidyverse terutama konsep piping %>% sehingga mempermudah dalam proses analisa. Sebelum menggunakan functions yang ada pada tidyverse kita harus memanggil function activate() terlebih dahulu. Kegunaan dari fungsi ini adalah untuk mengaktifkan data (nodes atau edges) yang akan digunakan.

gf_sample %>% 
  activate(what = nodes) %>% 
  mutate(id = row_number())
#> # A tbl_graph: 5 nodes and 6 edges
#> #
#> # An undirected simple graph with 1 component
#> #
#> # Node Data: 5 x 2 (active)
#>   name     id
#>   <chr> <int>
#> 1 B         1
#> 2 A         2
#> 3 D         3
#> 4 C         4
#> 5 E         5
#> #
#> # Edge Data: 6 x 2
#>    from    to
#>   <int> <int>
#> 1     1     3
#> 2     1     2
#> 3     3     4
#> # ... with 3 more rows

Code diatas mengaktifkan nodes, sehingga data tersebut dapat diolah dengan fungsi dari tidyverse. Pada contoh diatas dilakukan penambahan satu kolom yang bernama id yang berisi nomor baris dari nodes tersebut.

dengan menggunakan grammar dari tidyverse perhitungan nilai centrality pada suatu graph menjadi lebih mudah. perhitungan nilai centrality bisa dilakukan dengan mengaktivasi nodes kemudian menghitung centrality dari grapah tersebut dengan fungsi centrality_<jenisnya>()

gf_sample %>%
  activate(nodes) %>%
  mutate(
    betweenness = centrality_betweenness(normalized = T),
    eigen = centrality_eigen()
  )
#> # A tbl_graph: 5 nodes and 6 edges
#> #
#> # An undirected simple graph with 1 component
#> #
#> # Node Data: 5 x 3 (active)
#>   name  betweenness eigen
#>   <chr>       <dbl> <dbl>
#> 1 B           0.167 1    
#> 2 A           0.5   0.884
#> 3 D           0     0.757
#> 4 C           0.167 1    
#> 5 E           0     0.335
#> #
#> # Edge Data: 6 x 2
#>    from    to
#>   <int> <int>
#> 1     1     3
#> 2     1     2
#> 3     3     4
#> # ... with 3 more rows

Hasil perhitungan kedua centrality diatas yaitu betweenness dan eigen menunjukkan node A merupakan penghubung yang baik dikarenakan memiliki nilai betweenness tertinggi, sedangkan nodes B dan C memiliki nilai eigen tertinggi sehingga bisa diartikan nodes tersebut cukup baik dalam menyebarkan informasi pada suatu network.

4 Social Network Analysis

Social Network Analysis (SNA) merupakan sebuah teknik analisa hubungan/interaksi yang terjadi antar manusia dengan memanfaatkan teori graf.Interaksi antar manusia pun jadi jauh lebih mudah dianalisa dengan adanya media sosial, hal ini dikarenakan data tersebut terekam dan tersimpan oleh pemegang aplikasi. Data yang tersimpan dapat dimanfaatikan untuk mencari tahu “key player” dalam persebaran informasi, selain itu kita juga bisa mengetahui cluster pengguna dari suatu topik yang dibahas.

4.1 [Optional] Cara mengambil data dari twitter

Twitter merupakan salah satu media sosial yang dapat diambil datanya untuk digunakan dalam proses analisis. Data tersebut dapat diambil dengan menggunakan pacakge rtweet namun sebelum mengambil data dari twitter, pengguna harus memiliki akun twitter kemudian masuk (sign in) ke website twitter developer. Jika sudah lakukan beberapa tahapan dibawah ini untuk mendapatkan token dan key.

  1. Klik menu projects & Apps kemudian pilih Overview.
  2. Klik tombol Create App pada bagian Standalone Apps
  3. Masukkan nama app anda (contoh dss_sna) lalu klik Next.
  4. setelah itu anda akan mendapatkan API key, API key secret, dan bearer token. copy informasi tersebut dan pindahkan pada suatu text file sementara lalu klik App settings.
  5. untuk mendapatkan token dan secret token klik tab Key and tokens
  6. Klik Generate pada Access Token and Secret. Pastikan anda mensalin informasi Access Token dan Access Token Secret
  7. Klik Yes, I saved them jika sudah

Tahap mendapatkan akses ke twitter sudah selesai, sekarang kita sudah memiliki 4 informasi yang dibutuhkan untuk mengambil data dari twitter yaitu API Key, API Key Secret, access Token, dan access token secret. Keempat informasi tersebut bersifat sebagai username dan password ketika menarik data dari twitter sehingga informasi tersebut sangat rahasia. Untuk menjaga kerahasiaan informasi tersebut kita tidak boleh menyimpannya pada file .Rmd ini karena bisa saja informasi tersebut terkirim secara tidak sengaja. Informasi tersebut dapat disimpan pada sistem komputer sehingga kemungkinan informasi terambil lebih kecil.

Untuk meyimpan informasi Key dan token pada sistem bisa melakukan beberapa tahap dibawah ini:
1. Buat file yang bernama .Renviron.
2. Pindahkan informasi key dan token ke file tersebut. Pastikan format penulisannya sama dengan contoh dibawah.

access_token="858961976621383680-e70HtU6eVfky0SqkxeWNgxxxxxxxxxx"
access_token_secret="vvXjps6jia0VXI4PkO9txZrqq29FzLUuceJxxxxxxxxx"
Api_key="heuWLQt4EGBdISWxxxxxxxxxx"
api_key_secret="itxbcVBM8yybMWeGCY61MqwwK2JdDAJPGcfEp5QYxxxxxxxxxx"
  1. Simpan file .Renviron pada folder yang sama dengan materi ini disimpan.
  2. Restart RStudio anda dengan cara pilih menu Session, kemudian pilih restart R.
    Selamat sekarang informasi key dan token anda sudah tersimpan dengan aman pada sistem.

Sekarang data twitter bisa diambil namun sebelum itu kita harus connection dengan twitter dengan menggunakan fungsi create_token() dari package rtweet. Untuk memanggil informasi key dan token yang sudah disimpan pada system bisa menggunakan fungsi Sys.getenv() kemudian masukkan nama variabel yang ingin diambil.

library(rtweet)
my_token <- create_token(app = "davidAlgoritma",
             consumer_key = Sys.getenv("api_key"),
             consumer_secret = Sys.getenv("api_key_secret"),
             access_token = Sys.getenv("access_token"),
             access_secret = Sys.getenv("access_token_secret"))

Saat ini kita sudah bisa mengambil data dari twitter, ada banyak fungsi yang bisa digunakan untuk mengambil data dari twitter salah satunya yaitu search_tweets(). Terdapat beberapa parameter pada function tersebut untuk membantu pencarian tweet yang diinginkan seperti:
- q : keyword yang ingin anda cari di twitter.
- n : jumlah tweet yang ingin anda ambil.
- include_rts : apakah sebuah retweet akan diambil pada proses query.
- retryonratelimit : Apakah kita akan menunggu apabila limit dari penarikan data sudah tercapai?
untuk detail penjelasan dari setiap paramter bisa dilihat pada dokumentasi yang tersedia di menu help

national_tweet <- search_tweets(q = "#NationalChampionship",n = 100,include_rts = T,retryonratelimit = T)

Setelah tweet didapatkan pastikan anda menyimpan data tersebut dalam format .csv agar tidak perlu menarik data secara berulang kali.

write_as_csv(national_tweet, "national.csv")

4.2 Data Cleansing

Pada social network analysis setiap node direpresentasikan dengan user_name sedangkan edge bisa direpresentasikan dengan hubungan yang ada mention, retweet, maupun quote. Pada proses analisis kali ini kita akan melihat keterhubungan antar user berdasarkan mention yang ada pada tweet.

Tujuan dari proses cleansing ini untuk membuat raw data yang ada siap digunakan dalam proses pembuatan graph. Tahapan awal dari proses cleansing yaitu mengambil kolom screen_name, dan mentions_screen_name menggunakan select(), kedua kolom tersebut yang akan merepresentasikan nodes yang ada (from dan to pada data graph).

 tweets %>% 
  select(screen_name,mentions_screen_name) 

screen_name menunjukkan nama pengguna twitter yang memiliki sebuat tweet, sedangkan mentions_screen_name merupakan pengguna yang di mention pada tweet-nya. Bila dilihat kolom mentions_screen_name masih memiliki beberapa nama dalam satu baris, hal tersebut harus di normalisasi agar satu baris hanya terdiri dari satu pasang saja.

namun seebelum itu kita perlu menghapus string “c()” yang ada kolom mentions_screen_name. Proses penghapusan string dengan pattern tertentu dapat dilakukan dengan fungsi str_remove_all() kemudian masukkan pattern yang ingin di remove. Jika anda tertarik untuk mempelajari pattern pada suatu text silahkan kunjungi link berikut regex in r.

 tweets %>% 
  select(screen_name,mentions_screen_name) %>% 
  mutate(mentions_screen_name =str_remove_all(string = mentions_screen_name, 
                                               pattern = "^c\\(|\\)$"))

Sekarang kita sudah memisahkan data yang memiliki beberapa nilai pada kolom mentions_screen_name menjadi beberapa baris dengan fungsi separate_rows().

 tweets %>% 
  select(screen_name,mentions_screen_name) %>% 
  mutate(mentions_screen_name =str_replace_all(string = mentions_screen_name, 
                                               pattern =  "^c\\(|\\)$", 
                                               replacement = "")) %>% 
  separate_rows(mentions_screen_name,sep = ",")

Tahap terkahir yaitu kita bisa membuang semua data yang mengandung NA dengan fungsi na.omit() serta membuang tanda petik (“) yang tertinggal pada kolom mentions_screen_name. sebagai tambahan kita bisa mengubah nama kolom screen_name menjadi from dan mentions_screen_name dengan to.

edge_df <-
 tweets %>% 
  select(screen_name,mentions_screen_name) %>% 
  mutate(mentions_screen_name =str_replace_all(string = mentions_screen_name, 
                                               pattern =  "^c\\(|\\)$", 
                                               replacement = "")) %>% 
  separate_rows(mentions_screen_name,sep = ",") %>% # memisahkan data menjadi beberapa baris berdasarkan koma (,)
  na.omit() %>%  # menghapus NA pada data
  mutate(mentions_screen_name =str_replace_all(string = mentions_screen_name, # menghapus tanda baca pada kolom
                                               pattern =  "[[:punct:] ]+", 
                                               replacement = "")) %>% 
  rename(from = screen_name, # mengubah nama kolom
         to = mentions_screen_name)
head(edge_df)

setelah melakukan data cleansing untuk membuat data edges, satu lagi data yang dibutuhkan yaitu data nodes. Data nodes bisa didapatkan dari semua user name yang ada pada data edges.

# create nodes dataframe by unique value in both edges column
nodes_df <- data.frame(name = unique(c(edge_df$from,edge_df$to)),
                        stringsAsFactors = F)

tail(nodes_df)

setelah mendapatkan semua data, sekarang graph bisa dibentuk dengan menggunakan fungsi tbl_graph(). Pada parameter directed kita menggunakan FALSE yang berarti graph ini merupakan undirected graph, dengan membuatnya menjadi undirected hubungan antar node dapat dilihat dari 2 arah.

Anda juga dapat membuatnya menjadi directed bila asumsi yang digunakan adalah hubungan antar node belum tentu dua arah.

graph_tweets <- tbl_graph(nodes = nodes_df, 
                          edges = edge_df,
                          directed = F)

4.3 Centrality Mesurements

Setelah membuat graph kita bisa menghitung nilai centrality untuk tiap node. Ukuran centrality yang digunakan disini ada 4 yaitu degree, betweenness, closeness dan eigen.

graph_tweets <- graph_tweets %>% 
  activate(nodes) %>%
  mutate(degree = centrality_degree(), # Calculate degree centrality
         between = centrality_betweenness(normalized = T), # Calculate betweeness centrality
         closeness = centrality_closeness(), # Calculate closeness centrality
         eigen = centrality_eigen()
         )  # Calculate eigen centrality

Untuk melihat hasil dari perhitungan centrality diatas, data nodes dapat diambil dalam bentuk dataframe agar lebih mudah dianalisa lebih lanjut.

network_act_df <- graph_tweets %>% 
  activate(nodes) %>% 
  as.data.frame()

head(network_act_df)

Dari data diatas bisa dilihat tiap node memiliki nilai centrality yang berbeda beda, untuk mengetahui user name yang memiliki nilai tertinggi untuk masing masing ukuran centrality kita dapat mengubahnya menjadi format dibawah.

kp_activity <- data.frame(
  network_act_df %>% arrange(-degree) %>% select(name) %>% slice(1:6),
  network_act_df %>% arrange(-between) %>% select(name) %>% slice(1:6),
  network_act_df %>% arrange(-closeness) %>% select(name) %>% slice(1:6),
  network_act_df %>% arrange(-eigen) %>% select(name) %>% slice(1:6)
) %>% setNames(c("degree","betweenness","closeness","eigen"))
kp_activity

Dari data diatas kita bisa melihat bahwa akun DrRobDavidson merupakan akun dengan nilai eigen dan degree tertinggi yang berarti akun tersebut yang paling “populer” baik secara local maupun global network. DrRobDavidson merupakan seorang executive director of Committee to Protect Medicare.

tweets %>% 
  filter(mentions_screen_name == "DrRobDavidson") %>% 
  arrange(desc(mentions_screen_name)) %>% 
  distinct(text) %>% 
  pull(text)
#> [1] "Bottom line: If we see a big spike in #COVID19 cases, it's due to lack of testing &amp; contact tracing, &amp; a weak president rushing to reopen society prematurely for political reasons. Don’t let @realdonaldtrump use politics to rewrite history or shift blame. #BlackLivesMatter 8/8"
#> [2] "The president has a transparent motive to link a rise in #COVID19 to #peacefulprotests against police brutality. However, reopening entire states nationwide is far more risky than targeted protests in select cities. We wouldn’t see an impact of protests for another few wks. 4/8"       
#> [3] "We’re seeing a spike in cases of #COVID19 in AR, AZ, CA, MA, NC, NH, NV, OK, SC, TN, UT, and WA.And FL saw the most cases in 1 day this week. The cause? The rushed &amp; reckless #reopeningofAmerica pushed by @realDonaldTrump while failing to implement a national testing program. 2/8" 
#> [4] "Further, while there may be risk of getting #COVID19 from gathering close to others, the risk of an African American man dying at the hands of the police in their lifetime is 1/1000. Which means the current state of policing in America is a public health crisis. 5/8"                   
#> [5] "The difference between these protests &amp; anti-lockdown protests of weeks past? Previous protests opposed the very measures that were clearly flattening the curve of #COVID19. This week’s protests oppose measures that are killing Americans. They’re opposites. 6/8"                    
#> [6] "#coronavirus #COVID19\n#MemorialDayWeekend \n\nTHREAD\n\nBy @DrRobDavidson https://t.co/F82jwaowmu"

kita juga bisa melihat tweet dari WHO (World Health Organization) yang sering mengupdate perkembangan covid selama 2019.

tweets %>% 
  filter(mentions_screen_name == "WHO") %>% 
  arrange(desc(mentions_screen_name)) %>% 
  distinct(text) %>% 
  pull(text) %>% 
  head()
#> [1] "WHO updated guidance on the use of masks for control of #COVID19: https://t.co/z6DTZLG5Qs\n\nThe new guidance is based on evolving evidence and provides updates on:\n\n<U+0001F637>who should wear a mask\n\n<U+0001F637>when a mask should be worn\n\n<U+0001F637>what a mask should be made of https://t.co/Cu7MEyCs3J"
#> [2] "Elderly #Tamil Nadu #Chennai lady, who never stepped out of house for past 2 months, contracts #COVID19 #coronavirus. \n\n#health #pandemic @WHO https://t.co/JwDeVe1ta9"                                                                                                                                                 
#> [3] "\"Our guidance also explains how to use a mask safely. \n\nPeople can potentially infect themselves if they use contaminated hands to adjust a mask, or to repeatedly take it off and put it on, without cleaning hands in between\"-@DrTedros #COVID19 https://t.co/YO5eUQWdWv"                                          
#> [4] "Remember pple complained about Religious Institutions opening, not essential, etc. Only 50 pple allowed. Social Distancing, At funerals, etc. #BlackLivesMattters destroyed #COVID19. @WHO #Plandemic #Scamdemic #LockdownSA #CoronaVirusSA https://t.co/jallIJYAjO"                                                      
#> [5] "New guidelines by @WHO on using non-medical fabric #Masks. Here's do's &amp; don'ts you need to know to stay away from #COVID19 https://t.co/iv8gFf3Vz5"                                                                                                                                                                  
#> [6] "#COVID19 confirmed cases and deaths in the @WHO Western Pacific Region as of 10am Manila time on 7 June <U+0001F447>\n\n<U+27A1> For more info on #coronavirus cases in the region, see the dashboard here: https://t.co/EIf3BcbBF7 https://t.co/GRFQH14d3N"

4.4 Graph Visualization

Dari hasil pembuatan graph dan perhitungan nilai centrality kita dapat memvisualisasikan graph tersebut. Untuk mempermudah interpretasi dari plot nantinya kita perlu mengelompokkan nodes kedalam beberapa cluster. Oleh sebab itu kita akan melakukan proses clustering pada graph terlebih dahulu.

Metode clustering yang digunakan pada graph ini adalah metode Louvain, dimana metode ini melihat kerapatan (density) dari network yang ada. Untuk eksplorasi lebih lanjut terkait metode ini bisa kunjungi atikel berikut

set.seed(123)
graph_tweets <- graph_tweets %>% 
  activate(nodes) %>% 
  mutate(community = group_louvain()) %>% 
  activate(edges) %>% 
  filter(!edge_is_loop())  # Remove loop edges

Fungsigroup_louvain() bertujuan membuat cluster dengan metode louvain serta melakukan pelabelan secara langsung untuk tiap nodes. Bila dilihat dari rangkuman cluster yang terbentuk terdapat 3794 yang terbentuk, namun kita hanya akan fokus pada 5 cluster pertama saja karena cluster tersebut merupakan cluster terbesar.

graph_tweets %>% 
  activate(nodes) %>% 
  as.data.frame() %>% 
  count(community)
# fungsi untuk mendapatkan orang orang penting di tiap cluster
important_user <- function(data) {
  name_person <- data %>%
  as.data.frame() %>% 
  filter(community %in% 1:5) %>% 
  select(-community) %>% 
  pivot_longer(-name, names_to = "measures", values_to = "values") %>% 
  group_by(measures) %>% 
  arrange(desc(values)) %>% 
  slice(1:6) %>% 
  ungroup() %>% 
  distinct(name) %>% 
  pull(name)
  
  return(name_person)
}

Agar visualisasi yang ditampilkan tidak berantakan, maka label user_name yang ditampilkan hanyalah akun akun dengan nilai centrality tertinggi di tiap tiap clusternya.

important_person <- 
graph_tweets %>% 
  activate(nodes) %>% 
  important_user()
set.seed(13)
graph_tweets %>%
  activate(nodes) %>%
  mutate(ids = row_number(),
         community = as.character(community)) %>%
  filter(community %in% 1:5) %>% 
  arrange(community,ids) %>%
  mutate(node_label = ifelse(name %in% important_person, name,NA)) %>%
  ggraph(layout = "fr") +
  geom_edge_link(alpha = 0.3 ) +
  geom_node_point(aes(size = degree, fill = community), shape = 21, alpha = 0.7, color = "grey30") +
  geom_node_label(aes(label = node_label), repel = T, alpha = 0.8 ) +
  guides(size = "none") +
  labs(title = "Top 5 Community of #COVID19", 
       color = "Interaction",
       fill = "Community") +
  theme_void() +
  theme(legend.position = "top")

Dari visualisasi graph diatas kita bisa melihat 5 terdapat cluster. Masing masing cluster memiliki beberapa akun penting berdasarkan nilai centralitynya, semakin besar ukuran node menandakan semakin “populer” node tersebut (eigen centrality yang tinggi). Visualisasi diatas juga menunjukkan kerapatan yang berbeda dari masing masing cluster, semakin rapat suatu cluster maka persebaran informasi semakin efisien.