Pendahuluan

Sebagai makhluk sosial, semua manusia tidak lepas dari interaksi antara sesama manusia itu sendiri. Interaksi dapat dilakukan baik secara langsung maun secara tidak langsung (melalui sosial media misalnya seperti twitter, facebook, instagram dan lain sebagainya).

Sebagai contoh dengan twitter kita dapat berinteraksi dengan orang lain yang berbeda jarak dengan kita (di luar negeri atau luar daerah), sehingga kita dapat mengetahui berbagai informasi dan berita yang terupdate secara cepat.

Dengan adanya media sosial (twitter) kita juga dapat menganalisa inetraksi antar pengguna twitter itu sendiri, salah satu analisa yang digunakan adalah social network analysis.

Library dan Setup

Library yang digunakan pada analisa ini adalah sebagai berikut :

library(tidyverse)

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

Langkah pertama yang kita lakukan adalah setup library yang ada di atas, kemudian di run.

Exploratory Data Analysis

Langkah kedua yang kita lakukan adalah read data yang akan kita gunakan untuk analisa (nft.RDS) . Ketik kode program seperti langkah di bawah ini, kemudian di run.

tweets <- read_rds("nft.RDS")

Sebelum membuat 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 data yang merupakan sebuah retweet adalah sebanyak 13058.

Kita ingin mengetahui siapa sih akun (screen_name) dengan jumlah retweet terbanyak, maka langkah yang kita lakukan adalah sbb :

  1. Lakukan langkah seperti dibawah ini
tweets %>% 
  filter(is_retweet) %>% 
  select(retweet_count) %>% 
  summary()
##  retweet_count  
##  Min.   :    0  
##  1st Qu.:   88  
##  Median :  458  
##  Mean   : 1379  
##  3rd Qu.: 1395  
##  Max.   :49552

Maka dari hasil diatas di dapatkan hasil bahwa tweet maksimal di retweet sebanyak 49552 kali.

  1. Kemudian kita lakukan gunakan function filter(max) dan function select
tweets %>% 
  filter(retweet_count == max(retweet_count)) %>% 
  select(screen_name)

Maka akun (screen_name) dengan jumlah retweet berbanyak adalah “b1nary_eth”.

Data cleansing

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).

# Mengambil kolom `screen_name`, dan `mentions_screen_name`
tweets %>% 
  select(screen_name, mentions_screen_name)
# Membersihkan string pada kolom `mention_screen_name`
tweets %>% 
  select(screen_name,mentions_screen_name) %>% 
  mutate(mentions_screen_name = str_remove_all
         (string = mentions_screen_name, 
          pattern = "^c\\(|\\)$"))
# Memisahkan beberapa nama pada kolom `mention_screen_name` menjadi beberapa baris
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 = ",")
# Menghapus missing value (NA) pada data
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 = ",") %>% 
  na.omit()
# menghapus tanda baca pada kolom `mention_screen_name`
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 = ",") %>%  
  na.omit() %>% 
  mutate(mentions_screen_name = str_replace_all(string = mentions_screen_name,
                                               pattern =  "[[:punct:] ]+", 
                                               replacement = ""))
# mengubah nama `screen_name` menjadi `from` dan `mention_screen_name` menjadi `to`
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 = ",") %>%
  na.omit() %>% 
  mutate(mentions_screen_name = str_replace_all(string = mentions_screen_name,
                                               pattern =  "[[:punct:] ]+", 
                                               replacement = "")) %>% 
  rename(from = screen_name,
         to = mentions_screen_name)
# Simpan data yang sudah dicleansing menjadi edge_df

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 = ",") %>%
  na.omit() %>%
  mutate(mentions_screen_name = str_replace_all(string = mentions_screen_name,
                                               pattern =  "[[:punct:] ]+", 
                                               replacement = "")) %>% 
  rename(from = screen_name,
         to = mentions_screen_name)
head(edge_df)

setelah melakukan data cleansing untuk membuat data edges, satu lagi data yang dibutuhkan yaitu data nodes. Kita buat data frame yang bernama nodes_df yang berisi kumpulan screen_name yang ada pada data edge_df.

nodes_df <- data.frame(name = unique(c(edge_df$from,edge_df$to)))

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.

Kita buat graph menggunakan fungsi tbl_graph()

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

Centrality Measurement

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

Lakukan perhitungan nilai centrality dari graph

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

Ambil nilai centrality tersebut dan ubah menjadi data frame 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 akun yang memiliki nilai centrality 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 GenWealth0 merupakan akun dengan nilai betweenness dan closeness tertinggi.

Graph Visualization

Langkah selanjutnya adalah membuat graph, sebelum membuat graph terlebih dahulu lakukan clustering (pengelompokan).

set.seed(123)
graph_tweets <- graph_tweets %>% 
  activate(nodes) %>% 
  mutate(community = group_louvain()) %>% # melakukan clustering
  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.

Kemudian lakukan langkah dibawah ini untuk mendapatkan orang orang penting di tiap cluster.

# 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.

graph_tweets %>% 
  activate(nodes) %>%
  as.data.frame() %>%  # mengubah nodes menjadi dataframe
  filter(community %in% 1:5) %>% # mengambil community yang bernilai 1 sampai 5
  select(-community) %>% # menghapus colom community
  pivot_longer(-name, names_to = "measures", values_to = "values") %>% # mengubah data wide format menjadi long format
  group_by(measures) %>% # data dikelompokkan berdasarkan measures(nilai centrality)
  arrange(desc(values)) %>% # diurutkan datanya berdsarkan nilai centrality
  slice(1:6) %>% # diambil 6 nilai terbesar dari masing masing centrality
  ungroup() %>% # pengelompokan data dilepaskan
  distinct(name) %>%  # mengambil nama2 yang uniqe
  pull(name) # mengambil kolom nama saja
##  [1] "GenWealth0"     "opensea"        "nftspartan"     "TastyBonesNFT" 
##  [5] "misscryptolog"  "bgrathod6"      "smolrunnersNFT" "JAYNFTs"       
##  [9] "REALSWAK"       "CryptoKing1st"  "snowcorp"       "mandytn98"     
## [13] "Arizona998"     "mandyyyNFT"     "meganXONFT"     "veejayart"     
## [17] "Gabby_NFT"

Mendapatkan important_person

important_person <- 
graph_tweets %>% 
  activate(nodes) %>% 
  important_user()


important_person
##  [1] "GenWealth0"     "opensea"        "nftspartan"     "TastyBonesNFT" 
##  [5] "misscryptolog"  "bgrathod6"      "smolrunnersNFT" "JAYNFTs"       
##  [9] "REALSWAK"       "CryptoKing1st"  "snowcorp"       "mandytn98"     
## [13] "Arizona998"     "mandyyyNFT"     "meganXONFT"     "veejayart"     
## [17] "Gabby_NFT"

Kemudian visualisasikan data graph yang sudah dibuat, langkahnya sbb :

set.seed(13)
graph_tweets %>%
  activate(nodes) %>%
  mutate(ids = row_number(),
         community = as.character(community)) %>%
  filter(community %in% 1:5) %>%    # ubah berdasarkan jumlah cluster yang ingin di analisa 1:berapa?
  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 = "SOCIAL NETWORK ANALYTICS", # judul plot
       color = "Interaction",
       fill = "Community") + # legend warna
  theme_void() +
  theme(legend.position = "top")

## Kesimpulan

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 nilai (betweenness dan closeness tertinggi). Visualisasi diatas juga menunjukkan kerapatan yang berbeda dari masing masing cluster, semakin rapat suatu cluster maka persebaran informasi semakin efisien.