Ketika menghadapi digitalisasi, “literasi digital” masih menjadi pekerjaan rumah bagi Indonesia. Maraknya berita bohong, misinterpretasi, hal-hal yang viral dengan cepat, kerap kali menyebabkan kegaduhan maupun degradasi intelektual di masyarakat.
The Inclusive Internet Index, The Economist (2021)
Menurut The Inclusive Internet Index (by The Economist Intelligence Unit), Indonesia menempati urutan ke 72 di dunia ketika kita berbicara tentang kesiapan terhadap digitalisasi (meliputi Literasi Digital, Kebijakan, dan Internet Safety).
Berdasarkan data di atas, saya melihat bahwa harus ada upaya yang konsisten dari masa ke masa dalam peningkatan hal kesiapan digital. Salah satu upaya yang dapat dilakukan adalah, mengedukasi masyarakat tentang hal yang mungkin laten; yang tidak mereka sadari sebelumnya–yaitu bagaimana masyarakat bisa menganalisis isu-isu yang mereka sukai dengan melihat pola interaksi antar akun sosial media.
Warganet Indonesia cukup reaktif dalam menanggapi suatu hal di media sosial (khususnya Twitter). Bentuk-bentuk arus konten di twitter Indonesia saya bedakan secara garis besar, antara lain: - Berita - Respon perorangan - Respon buzzer - Respon tidak serius (nyeleneh)
Selain itu, pemetaan interaksi akun-akun pasti akan sangat menarik untuk dilihat. Saya tertarik pada berbagai publikasi Drone Emprit, sebuah platform publikasi SNA yang cukup dikenal pada kalangan akademisi ilmu sosial.
Maka dari itu, saya melihat bahwa Social Network Analysis dan Text Classification bisa menjadi salah satu repertoar yang baik untuk membangun literasi digital dimasyarakat. Dengan dikemas pada dashboard yang interaktif, saya berharap netizen bisa mengeksplor fitur yang ada di dalamnya sambil mempelajari stream informasi pada suatu topik (hashtags, query) yang mereka sukai.
Dashboard ini dapat saja digunakan bagi kebutuhan bisnis, pemerintah, maupun awam. Ide ini tidak tertutup kemungkinan pada luasnya latar belakang netizen di Indonesia.
Dengan memetakan pola interaksi dan sentimen, suatu bisnis maupun perseorangan dapat memperoleh pemetaan tentang pola relasi, komunitas/segmen, maupun respon suatu populasi (di Twitter) terhadap topik tertentu.
Sebetulnya, target user utama dari dashboard ini tidak lain adalah warganet itu sendiri. Selain itu dashboard ini diharapkan dapat mendekatkan framework analisis data social behavior/user generated data kepada awam dan akademisi sosial.
Konsep SNA dan Text Classification dapat diimplementasi pada kasus-kasus berikut ini:
Akademisi sosial dapat menganalisis data twitter dengan mudah tanpa harus menunggu publikasi dari beberapa organisasi yang biasa mengolah data social network (seperti Lab Big Data, Drone Emprit, dsb).
Misalkan divisi marketing ingin melihat customer segmentation, mereka juga dapat menggunakan data dari hashed emails ataupun user-generated data yang mereka miliki menggunakan metode graph analytics.
Misalkan ketika suatu trade saham maupun komoditas (crypto, forex) akan menghadapi suatu musim (politik, dsb) bagaimana kemudian perusahaan bisa mengambil sikap untuk meningkatkan atau mengurangi jumlah investasi pada sektor tertentu berdasarkan analisis sentimen, pastinya dengan menggunakan data train yang sudah disesuaikan klasifikasinya, misalkan emotional sentiment.
Misalkan web developer ingin memahami efisiensi website mereka menggunakan data cookies, kita dapat mewakili setiap page sebagai nodes melalui graph analytics.
Misalkan web developer ingin memahami efisiensi website mereka menggunakan data cookies, kita dapat mewakili setiap page sebagai nodes melalui graph analytics.
Divisi human capital suatu perusahaan pun dapat menggunakan framework serupa (graph analytics) untuk keperluan organizational network analysis.
Project ini diharapkan mampu menjawab visi diatas, dengan menggunakan algoritma clustering dan Long Short Term Memory untuk analisis sentimen.
Karena project ini salah satunya akan menggunakan unsupervised learning, sepertinya saya membutuhkan lebih dari satu dataset untuk dapat memastikan bahwa dashboard berjalan dengan baik.
Sejauh ini, data twitter yang saya miliki adalah data dari DSS Social Network Analysis. Saya ingin mengeksplor lebih jauh terkait kemungkinan error yang dapat terjadi dari graph analytics. Misalkan username yang tidak valid yang disebabkan kesalahan dalam cleansing, kesalahan dalam pengambilan data, dsb.
Data dari DSS tersebut diambil dari twitter API (Mas David) dengan topik “NFT”. Sementara Data untuk text classification belum dapat saya peroleh karena terkendala submission di Twitter Developer.
Pasti sesuai karena saya ingin membuat dashboard yang memungkinkan pengolahan berbagai data dengan struktur yang serupa (twitter API, menggunakan fitur import/upload to dashboard).
Unsupervised: tidak ada
Text Classification : Text dan Label (berita, respon perorangan, respon buzzer, respon tidak serius)
Mengajukan izin twitter developer (terkendala)
Cleansing data untuk train model SNA dan Text Classification, membersihkan beberapa style text dari twitter API menggunakan regular expression dan beberapa package cleansing
Memisahkan “mentions” dari teks ke kolom terpisah
Mengambil data untuk text klasifikasi, memberi label secara manual (tableplus)
library(tidyverse)
# graph
library(tidygraph)
library(ggraph)
library(igraph)tweets <- read_rds("nft.RDS")
head(tweets, 10)tail(tweets, 20)glimpse(tweets)#> Rows: 17,681
#> Columns: 90
#> $ user_id <chr> "1482989135279554561", "1465321321018101774", ~
#> $ status_id <chr> "1484077026751705091", "1484077026546008068", ~
#> $ created_at <dttm> 2022-01-20 08:15:10, 2022-01-20 08:15:10, 202~
#> $ screen_name <chr> "MdMurad46986696", "artur_litau", "uzayhayat17~
#> $ text <chr> "<U+0001F6F8>There are different crystals on the earth. ~
#> $ source <chr> "Twitter Web App", "Twitter for iPhone", "Twit~
#> $ display_text_width <dbl> 140, 13, 4, 69, 140, 140, 140, 140, 139, 140, ~
#> $ reply_to_status_id <chr> NA, "1484076661943513088", "148407336790914663~
#> $ reply_to_user_id <chr> NA, "1469819305", "1728743684", NA, NA, NA, NA~
#> $ reply_to_screen_name <chr> NA, "drmctchr333", "misscryptolog", NA, NA, NA~
#> $ is_quote <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALS~
#> $ is_retweet <lgl> TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TR~
#> $ favorite_count <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0~
#> $ retweet_count <int> 4105, 0, 0, 1305, 822, 264, 13, 1, 344, 1942, ~
#> $ quote_count <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ reply_count <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ hashtags <list> NA, NA, NA, NA, NA, <"NFTs", "HODL", "gems", ~
#> $ symbols <list> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "REVO~
#> $ urls_url <list> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N~
#> $ urls_t.co <list> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N~
#> $ urls_expanded_url <list> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N~
#> $ media_url <list> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N~
#> $ media_t.co <list> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N~
#> $ media_expanded_url <list> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N~
#> $ media_type <list> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N~
#> $ ext_media_url <list> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N~
#> $ ext_media_t.co <list> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N~
#> $ ext_media_expanded_url <list> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N~
#> $ ext_media_type <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ mentions_user_id <list> "717023423696871424", <"1469819305", "1441155~
#> $ mentions_screen_name <list> "SpaceDAOBSC", <"drmctchr333", "BabyGhosts_NF~
#> $ lang <chr> "en", "en", "en", "en", "en", "en", "en", "en"~
#> $ quoted_status_id <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ quoted_text <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ quoted_created_at <dttm> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N~
#> $ quoted_source <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ quoted_favorite_count <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ quoted_retweet_count <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ quoted_user_id <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ quoted_screen_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ quoted_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ quoted_followers_count <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ quoted_friends_count <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ quoted_statuses_count <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ quoted_location <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ quoted_description <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ quoted_verified <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ retweet_status_id <chr> "1483999732905111552", NA, NA, "14840733679091~
#> $ retweet_text <chr> "<U+0001F6F8>There are different crystals on the earth. ~
#> $ retweet_created_at <dttm> 2022-01-20 03:08:02, NA, NA, 2022-01-20 08:00~
#> $ retweet_source <chr> "Twitter Web App", NA, NA, "Twitter for iPhone~
#> $ retweet_favorite_count <int> 4046, NA, NA, 369, 813, 272, 19, 1, 377, 1173,~
#> $ retweet_retweet_count <int> 4105, NA, NA, 1305, 822, 264, 13, 1, 344, 1942~
#> $ retweet_user_id <chr> "717023423696871424", NA, NA, "1728743684", "3~
#> $ retweet_screen_name <chr> "SpaceDAOBSC", NA, NA, "misscryptolog", "Brecc~
#> $ retweet_name <chr> "SpaceDAO", NA, NA, "Miss Cryptolog", "Brecci"~
#> $ retweet_followers_count <int> 51808, NA, NA, 557859, 187762, 124776, 341, 78~
#> $ retweet_friends_count <int> 128, NA, NA, 281, 846, 235, 2, 3149, 166, 11, ~
#> $ retweet_statuses_count <int> 48, NA, NA, 13019, 10258, 2349, 71, 259, 122, ~
#> $ retweet_location <chr> "Metaverse", NA, NA, "", "DM for PAID promo <U+0001F525>~
#> $ retweet_description <chr> "SpaceDAO innovation on GameFi world!\nTelegra~
#> $ retweet_verified <lgl> FALSE, NA, NA, FALSE, TRUE, FALSE, FALSE, FALS~
#> $ place_url <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ place_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ place_full_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ place_type <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ country <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ country_code <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ geo_coords <list> <NA, NA>, <NA, NA>, <NA, NA>, <NA, NA>, <NA, ~
#> $ coords_coords <list> <NA, NA>, <NA, NA>, <NA, NA>, <NA, NA>, <NA, ~
#> $ bbox_coords <list> <NA, NA, NA, NA, NA, NA, NA, NA>, <NA, NA, NA~
#> $ status_url <chr> "https://twitter.com/MdMurad46986696/status/14~
#> $ name <chr> "Md Murad", "Artur Litau", "Uzay Hayat", "Uzay~
#> $ location <chr> "", "", "", "", "", "", "", "", "", "", "Lagos~
#> $ description <chr> "", "", "#SUPERFAMILY\n@LaCryptoMonkey\n#RichQ~
#> $ url <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "h~
#> $ protected <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALS~
#> $ followers_count <int> 2, 4, 302, 302, 96, 96, 299, 299, 6, 6, 43, 52~
#> $ friends_count <int> 55, 34, 4163, 4163, 4838, 4838, 732, 732, 1357~
#> $ listed_count <int> 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0~
#> $ statuses_count <int> 166, 44, 21653, 21653, 50394, 50394, 2316, 231~
#> $ favourites_count <int> 78, 76, 17321, 17321, 9710, 9710, 2076, 2076, ~
#> $ account_created_at <dttm> 2022-01-17 08:12:36, 2021-11-29 14:07:40, 202~
#> $ verified <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALS~
#> $ profile_url <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "h~
#> $ profile_expanded_url <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "h~
#> $ account_lang <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ profile_banner_url <chr> NA, NA, "https://pbs.twimg.com/profile_banners~
#> $ profile_background_url <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
#> $ profile_image_url <chr> "http://pbs.twimg.com/profile_images/148298921~
tweets %>%
count(is_retweet)tweets %>%
filter(is_retweet) %>%
select(retweet_count) %>%
summary()#> retweet_count
#> Min. : 0
#> 1st Qu.: 88
#> Median : 458
#> Mean : 1379
#> 3rd Qu.: 1395
#> Max. :49552
tweets %>%
filter(retweet_count == 49552) %>%
select(screen_name,user_id, text)User dengan screen name b1nary_eth merupakan akun dengan jumlah retweet terbanyak pada dataset. adapun isi tweet tersebut dapat kita pahami sebagai pertanyaan sekaligus pertanyaan tentang in-game-currency yang menggunakan NFT. Bagaiamana kemudian berbagai game-NFT dapat bertahan, karena banyak entitas serupa justru tidak mampu bertahan karena kebijakan in game currency nya sendiri (menggunakan NFT/kripto).
(lihat referensi di sini)
cleansing <- tweets %>%
select(screen_name, mentions_screen_name) %>%
mutate(mentions_screen_name = as.character(mentions_screen_name))
head(cleansing, 100)mentions_screen_name menggunakan regular expression–> sekaligus menyiapkan objek edge_df
edge_df <-
cleansing %>%
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, 100)nodes_df (kumpulan screen_name pada edge_df)nodes_df <- data.frame(name = unique(c(edge_df$from,edge_df$to)),
stringsAsFactors = F)
tail(nodes_df,10)Antara data edge dan nodes belum terlalu rapi, masih ada quotation mark (" "), saya ingin membersikan menggunakan regex pada function str_replace_all
nodes_df1 <- nodes_df %>%
mutate(name = str_replace_all(string = name,
pattern = "\"",
replacement = ""))
head(nodes_df1)edge_df1 <- edge_df %>%
mutate(to = str_replace_all(string = to,
pattern = "\"",
replacement = ""))
head(edge_df1)graph_tweets <- tbl_graph(nodes = nodes_df1,
edges = edge_df1,
directed = F)
graph_tweets#> # A tbl_graph: 18490 nodes and 33011 edges
#> #
#> # An undirected multigraph with 1882 components
#> #
#> # Node Data: 18,490 x 1 (active)
#> name
#> <chr>
#> 1 MdMurad46986696
#> 2 artur_litau
#> 3 uzayhayat17
#> 4 _andierna_
#> 5 Cardatson
#> 6 minguinnnnn_
#> # ... with 18,484 more rows
#> #
#> # Edge Data: 33,011 x 2
#> from to
#> <int> <int>
#> 1 1 9504
#> 2 2 9505
#> 3 2 9506
#> # ... with 33,008 more rows
Saya menggunakan undirected graph karena ingin mengabaikan arah interaksi antara from dan to, dan apakah interaksi terjadi secara dua arah atau searah.
Kita akan mengukur centrality dari setiap Nodes dengan parameter berikut:
Degree: untuk menemukan user yang terkoneksi secara lokal (dalam satu cluster)
Betweenness: untuk menemukan user yang menjadi perantara terhadap beberapa cluster
Closeness: untuk menemukan user yang memiliki bisa memberi influence tercepat terhadap yang lain
Eigen: mengukur pengaruh dari setiap user dari banyaknya keterhubungan dengan node-node lainnya; lalu dipertimbangkan juga koneksi yang dimiliki oleh setiap user; bobot dari berbagai koneksi yang dimiliki
options(scipen = 100)
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
graph_tweets#> # A tbl_graph: 18490 nodes and 33011 edges
#> #
#> # An undirected multigraph with 1882 components
#> #
#> # Node Data: 18,490 x 5 (active)
#> name degree between closeness eigen
#> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 MdMurad46986696 1 0 0.00000000950 1.92e- 7
#> 2 artur_litau 3 0.000112 0.00000000949 3.21e-11
#> 3 uzayhayat17 4 0.0000000173 0.00000000950 6.88e- 2
#> 4 _andierna_ 3 0.000000984 0.00000000950 1.12e- 3
#> 5 Cardatson 2 0.0000000117 0.00000000293 7.35e-18
#> 6 minguinnnnn_ 3 0.0000130 0.00000000950 7.81e- 5
#> # ... with 18,484 more rows
#> #
#> # Edge Data: 33,011 x 2
#> from to
#> <int> <int>
#> 1 1 9504
#> 2 2 9505
#> 3 2 9506
#> # ... with 33,008 more rows
network_act_df <- graph_tweets %>%
activate(nodes) %>%
as.data.frame()
head(network_act_df,10)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_activityBerdasarkan hasil analisis centralities, terlihat bahwa akun f_sara termasuk dalam semua golongan centrality, yang berarti akun tersebut paling populer secara lokal maupun global (eigen).
Selain itu, besar kemungkinan jugaf_sara terhubung dengan kebanyakan cluster, sehingga arus informasi dari semua cluster diakomodasi oleh akun tersebut.
Namun, temuan dapat saja berbeda apabila terdapat aktivitas mentioning yang berlebihan yang ditujukan pada akun f_sara, terlepas dari apa dan siapa identitas akun tersebut.
# Memahami siapa f_sara
lookup <- tweets %>%
select(screen_name, mentions_screen_name, text, retweet_count) %>%
mutate(mentions_screen_name = as.character(mentions_screen_name)) %>%
mutate(mentions_screen_name = str_replace_all(string = mentions_screen_name,
pattern = "^c\\(|\\)$",
replacement = "")) %>%
na.omit() %>%
mutate(mentions_screen_name = str_replace_all(string = mentions_screen_name,
pattern = "[[:punct]]+",
replacement = "")) %>%
mutate(mentions_screen_name = str_replace_all(string = mentions_screen_name,
pattern = "\"",
replacement = "")) %>%
separate_rows(mentions_screen_name, sep = ",")
lookupinspect_sara <- lookup %>%
filter(mentions_screen_name == "f_sara") %>%
arrange(desc(retweet_count)) %>%
distinct(text, mentions_screen_name, screen_name)
inspect_sara[41:105,]Setelah pencarian lebih lanjut, sayangnya akun dengan nama screen_name f_sara tidak terkait dengan tweet bertopik NFT/kripto.
Berdasarkan data, kita dapat melihat bahwa f_sara sering terkait dengan tweet dari sebuah akun yang bernama @nft_spartan.
nft_spartan merupakan kolektor dan investor NFT, akun tersebut sering terlibat dalam suatu givaway maupun info dan ‘tips and trick’.
Dalam dunia yang sarat dengan unsur FOMO (Fear Of Missing Out) seperti game, cryptocurrency maupun NFT, kita mungkin sering melihat akun yang “menggaungkan isu” secara intensif/spamming.
Analisis saya, karena pada saat ini kita mengacu pada mentions_screen_name, kemungkinan besar akun nft_spartan melakukan mention secara acak dan hidden kepada beberapa screen name untuk memperkenalkan isi kontennya. Namun disayangkan, karena target mentionnya terlihat seperti akun nonaktif.
set.seed(123)
graph_tweets <- graph_tweets %>%
activate(nodes) %>%
mutate(community = group_louvain()) %>%
activate(edges) %>%
filter(!edge_is_loop()) # Remove loop edgesgraph_tweets %>%
activate(nodes) %>%
as.data.frame() %>%
count(community)Mengambil cluster 1-5 saja, dengan asumsi 5 data dari klaster terbanyak sudah representatif (jumlah dari n1-n5)
# 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)
}important_person <-
graph_tweets %>%
activate(nodes) %>%
important_user()set.seed(100)
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 #NFT",
color = "Interaction",
fill = "Community") +
theme_void() +
theme(legend.position = "top")Saya sedikit skeptis dengan hasil top 5 community diatas, bagaimana eksistensi akunnya di twitter, apakah sama seperti f_sara.
Maka dari itu saya ingin melihat screen_name, mentions_screen_name, dan text yang melibatkan akun yang saya curigai.
Saya tertarik untuk inspect akun missryolog.
missryolog <- lookup %>%
filter(mentions_screen_name == "missryolog") %>%
arrange(desc(retweet_count)) %>%
distinct(text, mentions_screen_name, screen_name)
head(missryolog,100)Dapat kita lihat dari isi tweet, bahwa pada akun missryolog pun masih berkaitan dengan spamming nft_spartan.
Selanjutnya, sebetulnya apa isi dari akun missryolog?
knitr::include_graphics("images/ryolog.png")Ternyata, missryolog bukanlah merupakan akun yang aktif (atau bahkan salah alamat). Dari hasil eksplorasi object yang sudah saya buat secara khusus, saya memiliki perkiraan bahwa missryolog merupakan kesalahan penulisan dari misscryptolog.
missryolog[991:1052,]knitr::include_graphics("images/cryptolog.png")Berdasarkan hasil visualisasi dan centrality, dapat disimpulkan bahwa cluster yang berwarna hijau yang memiliki keterhubungan dengan nodes dari cluster lainnya. Namun, sepertinya terdapat beberapa nama akun yang tidak valid; entah itu dikarenakan proses cleansing atau karena data asalnya (mohon pencerahan).
Banyak akun investor NFT yang melakukan spamming terhadap akun-akun lain secara acak, dilihat dari relevansi mentions_screen_name terhadap pemeriksaan eksistensi akun tersebut di twitter (contohnya: f_sara).
Akun @nft_spartan was a great spammer
library(networkD3)src <- c("A", "A", "A", "A",
"B", "B", "C", "C", "D")
target <- c("B", "C", "D", "J", "E",
"F", "G", "H", "I")
networkData <- data.frame(src, target)simpleNetwork(networkData)data("MisLinks")
data("MisNodes")forceNetwork(Links = MisLinks, Nodes = MisNodes, Source = "source",
Target = "target", Value = "value", NodeID = "name",
Nodesize = "size",
radiusCalculation = "Math.sqrt(d.nodesize)+6",
Group = "group", opacity = 1, opacityNoHover = F, width = 1000, height = 700, fontSize = 12)forceNetwork()MisLinksMisNodesStruktur data sedikit berbeda dengan ggraph.. apakah hasil tbl_graph() kompatibel untuk plotting NetworkD3?
Kesalahan cleansing, encoding, dsb
Interaksi mentions yang seakan membuat seseorang memiliki centrality tinggi, padahal akun tersebut merupakan “korban” spamming
Membuat directed graph
Mendapatkan data twitter secara real time
contoh tampilan page 1
contoh tampilan page 2
SNA (clustering, graph analytics directed dan undirected)
LSTM (untuk classification) –> arsitektur deep learning perlu dieksplorasi
Embed text Tweet berdasarkan hasil pembelajaran mesin (untuk klasifikasi)
Embed mock up profile berdasarkan centralities SNA (jika memungkinkan)
UI menggunakan framework bootstrap 4 di R-shiny
Satu halaman edukasi graph analytics (konsep masih dipikirkan)