系統參數設定
Sys.setlocale(category = "LC_ALL", locale = "zh_TW.UTF-8") # 避免中文亂碼## [1] ""
安裝需要的packages
packages = c("readr", "dplyr", "jiebaR", "tidyr", "tidytext", "igraph", "topicmodels", "ggplot2", "stringr")
existing = as.character(installed.packages()[,1])
for(pkg in packages[!(packages %in% existing)]) install.packages(pkg)讀進library
library(readr)
library(dplyr)
library(jiebaR)
library(tidyr)
library(tidytext)
library(igraph)
library(topicmodels)
library(stringr)
library(ggplot2)
library(reshape2)
library(wordcloud2)這次我們針對5/22發生的校正回歸事件,討論ptt版上相關討論的發文風向,主要針對以下方向分析:
1.校正回歸的討論重點有哪些? 主要分為哪幾種風向? 2.目前風向最偏哪邊? 3.討論校正回歸的社群網路如何分布? 4.校正回歸的意見領袖有誰?網友的推噓狀態如何?
在本篇分析中,我們希望建構特定議題的社群網路圖,並分析網路中討論的議題主題
我們需要兩種資料: (1) 每篇文章的主題分類(LDA) (2) 社群網路圖的link和nodes
載入文章和網友回覆資料
posts <- read_csv("../data/Corrected_articleMetaData.csv") # 文章 1399
reviews <- read_csv("../data/Corrected_articleReviews.csv") # 回覆 56079
head(posts)## # A tibble: 6 x 10
## artTitle artDate artTime artUrl artPoster artCat commentNum push boo
## <chr> <date> <time> <chr> <chr> <chr> <dbl> <dbl> <dbl>
## 1 [討論]陳時中~ 2021-05-20 16:32:18 https~ miler220~ HateP~ 21 11 0
## 2 Re:[討論]~ 2021-05-20 16:39:45 https~ Sinreige~ HateP~ 12 5 0
## 3 [新聞]外媒分~ 2021-05-20 16:54:25 https~ cheinshin HateP~ 329 77 3
## 4 [新聞]高雄疫~ 2021-05-20 18:28:16 https~ coober HateP~ 30 12 7
## 5 [新聞]金沙酒~ 2021-05-20 23:52:36 https~ cake10414 HateP~ 71 44 1
## 6 [新聞]蘇揆:~ 2021-05-21 01:36:12 https~ yataiml0~ HateP~ 14 5 4
## # ... with 1 more variable: sentence <chr>
head(reviews)## # A tibble: 6 x 10
## artTitle artDate artTime artUrl artPoster artCat cmtPoster cmtStatus
## <chr> <date> <time> <chr> <chr> <chr> <chr> <chr>
## 1 [討論]陳時中~ 2021-05-20 16:32:18 https~ miler220~ HateP~ SMG2016 推
## 2 [討論]陳時中~ 2021-05-20 16:32:18 https~ miler220~ HateP~ SMG2016 →
## 3 [討論]陳時中~ 2021-05-20 16:32:18 https~ miler220~ HateP~ tony1210~ 推
## 4 [討論]陳時中~ 2021-05-20 16:32:18 https~ miler220~ HateP~ tony1210~ →
## 5 [討論]陳時中~ 2021-05-20 16:32:18 https~ miler220~ HateP~ oscarwu3~ 推
## 6 [討論]陳時中~ 2021-05-20 16:32:18 https~ miler220~ HateP~ Atkins13 →
## # ... with 2 more variables: cmtDate <dttm>, cmtContent <chr>
文章斷句
# # 文章斷句("\n\n"取代成"。")
# mask_meta <- posts %>%
# mutate(sentence=gsub("[\n]{2,}", "。", sentence))
#
# # 以全形或半形 驚歎號、問號、分號 以及 全形句號 爲依據進行斷句
# mask_sentences <- strsplit(mask_meta$sentence,"[。!;?!?;]")
#
# # 將每句句子,與他所屬的文章連結配對起來,整理成一個dataframe
# mask_sentences <- data.frame(
# artUrl = rep(mask_meta$artUrl, sapply(mask_sentences, length)),
# sentence = unlist(mask_sentences)
# ) %>%
# filter(!str_detect(sentence, regex("^(\t|\n| )*$")))
# # 如果有\t或\n就去掉
#
# mask_sentences$sentence <- as.character(mask_sentences$sentence)
# mask_sentences文章斷詞
# ## 文章斷詞
# # load mask_lexicon(特定要斷開的詞,像是user_dict)
# mask_lexicon <- scan(file = "../dict/mask_lexicon.txt", what=character(),sep='\n',
# encoding='utf-8',fileEncoding='utf-8')
# # load stop words
# stop_words <- scan(file = "../dict/stop_words.txt", what=character(),sep='\n',
# encoding='utf-8',fileEncoding='utf-8')
#
# # 使用默認參數初始化一個斷詞引擎
# jieba_tokenizer = worker()
#
# # 使用口罩字典重新斷詞
# new_user_word(jieba_tokenizer, c(mask_lexicon))
#
# # tokenize function
# chi_tokenizer <- function(t) {
# lapply(t, function(x) {
# if(nchar(x)>1){
# tokens <- segment(x, jieba_tokenizer)
# tokens <- tokens[!tokens %in% stop_words]
# # 去掉字串長度爲1的詞彙
# tokens <- tokens[nchar(tokens)>1]
# return(tokens)
# }
# })
# }
#
#
# # 用剛剛初始化的斷詞器把sentence斷開
# tokens <- mask_sentences %>%
# mutate(sentence = gsub("[[:punct:]]", "",sentence)) %>%
# mutate(sentence = gsub("[0-9a-zA-Z]", "",sentence)) %>%
# unnest_tokens(word, sentence, token=chi_tokenizer) %>%
# count(artUrl, word) %>% # 計算每篇文章出現的字頻
# rename(count=n)
# tokens
# save.image(file = "../data/token_result.rdata")斷詞結果可以先存起來,就不用再重跑一次
load("../data/token_result.rdata")。根據詞頻,選擇只出現3字以上的字 。整理成url,word,n的格式之後,就可以轉dtm
P.S. groupby by之後原本的字詞結構會不見,把詞頻另存在一個reserved_word裡面
freq = 3
# 依據字頻挑字
reserved_word <- tokens %>%
group_by(word) %>%
count() %>%
filter(n > freq) %>%
unlist()
mask_removed <- tokens %>%
filter(word %in% reserved_word)
#mask_dtm 裡面 nrow:幾篇文章 ; ncol:幾個字
mask_dtm <- mask_removed %>% cast_dtm(artUrl, word, count) 將剛處理好的dtm放入LDA函式分析
# LDA分成4個主題
mask_lda <- LDA(mask_dtm, k = 4, control = list(seed = 123))p.s. 。tidy(mask_lda, matrix = “beta”) # 取字 topic term beta值 。tidy(mask_lda, matrix=“gamma”) # 取主題 document topic gamma
removed_word = c("不是","每天","出來","覺得")
# 看各群的常用詞彙
tidy(mask_lda, matrix = "beta") %>% # 取出topic term beta值
filter(! term %in% removed_word) %>%
group_by(topic) %>%
top_n(10, beta) %>% # beta值前10的字
ungroup() %>%
mutate(topic = as.factor(topic),
term = reorder_within(term, beta, topic)) %>%
ggplot(aes(term, beta, fill = topic)) +
geom_col(show.legend = FALSE) +
facet_wrap(~ topic, scales = "free") +
coord_flip() +
scale_x_reordered()可以歸納出
topic 1 = “確診足跡相關報導”
topic 2 = “批評嘲諷校正回歸”
topic 3 = “疫苗、相關報導”
topic 4 = “校正回歸報導相關”
以下我們挑出第二個主題與第四個主題來做比較。
每篇文章拿gamma值最大的topic當該文章的topic
# 在tidy function中使用參數"gamma"來取得 theta矩陣
mask_topics <- tidy(mask_lda, matrix="gamma") %>% # document topic gamma
group_by(document) %>%
top_n(1, wt=gamma)
mask_topics## # A tibble: 1,399 x 3
## # Groups: document [1,399]
## document topic gamma
## <chr> <int> <dbl>
## 1 https://www.ptt.cc/bbs/Gossiping/M.1621529006.A.AC9.html 1 0.998
## 2 https://www.ptt.cc/bbs/Gossiping/M.1621532471.A.AA9.html 1 0.653
## 3 https://www.ptt.cc/bbs/Gossiping/M.1621541287.A.6D6.html 1 0.721
## 4 https://www.ptt.cc/bbs/Gossiping/M.1621556811.A.D8B.html 1 0.411
## 5 https://www.ptt.cc/bbs/Gossiping/M.1621561439.A.245.html 1 0.996
## 6 https://www.ptt.cc/bbs/Gossiping/M.1621562304.A.5A3.html 1 0.937
## 7 https://www.ptt.cc/bbs/Gossiping/M.1621567320.A.4DA.html 1 0.998
## 8 https://www.ptt.cc/bbs/Gossiping/M.1621569423.A.2C3.html 1 0.997
## 9 https://www.ptt.cc/bbs/Gossiping/M.1621570638.A.FC5.html 1 0.998
## 10 https://www.ptt.cc/bbs/Gossiping/M.1621571819.A.362.html 1 0.999
## # ... with 1,389 more rows
posts_topic <- merge(x = posts, y = mask_topics, by.x = "artUrl", by.y="document")
# 看一下各主題在說甚麼
set.seed(123)
posts_topic %>% # 主題二
filter(topic==2) %>%
select(artTitle) %>%
unique() %>%
sample_n(5)## artTitle
## 1 [問卦]開派對可以校正回歸嗎?
## 2 [問卦]請問校正回歸,病患何時得知自己確診?
## 3 [問卦]教育部國語辭典查不到校正回歸
## 4 [問卦]因為疫情見不到男友::>_<::
## 5 [問卦]校正迴歸以後大家都是30+公分嗎
posts_topic %>% # 主題四
filter(topic==4) %>%
select(artTitle) %>%
unique() %>%
sample_n(5)## artTitle
## 1 Re:[新聞]校正回歸?柯文哲:檢驗塞車中央要用新
## 2 [問卦]會不會有二度校正回歸
## 3 [新聞]新增400例「校正回歸」 陳玉珍嗆:那何
## 4 [問卦]校正校正回歸
## 5 Re:[新聞]今突然出現「校正回歸400」柯文哲專業解
這次我們把討論焦點放在校正回歸上,從主題分布大概可以看到兩類觀點:
主題二: > 對於指揮中心公布校正回歸多持嘲諷態度,如「賠錢的股票都是屬於校正回歸嗎?」、「可以跟別人介紹我校正回歸女朋友嗎」、「我可以校正回歸上月營收嗎0_0?」、「有沒有估狗查不到校正回歸的八卦? 」
主題四: > 大部分是確診數字的討論,對於「校正回歸」多為客觀討論定義、數字應該怎麼計算才正確等等,如「當天篩檢當天全出報告,確診數字?」、「請問什麼是校正回歸?」、「每日確診數是怎麼計算的?」
畫出每天topic的分布,發現隨著時間增加,主題二、四的比例逐漸增加,且主題二的比例大於主題四。
posts_topic %>%
mutate(artDate = as.Date(artDate)) %>%
group_by(artDate,topic) %>%
summarise(sum =sum(topic)) %>%
ggplot(aes(x= artDate,y=sum,fill=as.factor(topic))) +
geom_col(position="fill") ## `summarise()` regrouping output by 'artDate' (override with `.groups` argument)
posts_topic %>%
group_by(artCat,topic) %>%
summarise(sum = n()) %>%
ggplot(aes(x= artCat,y=sum,fill=as.factor(topic))) +
geom_col(position="dodge") ## `summarise()` regrouping output by 'artCat' (override with `.groups` argument)
資料合併
# 文章和留言
reviews <- reviews %>%
select(artUrl, cmtPoster, cmtStatus, cmtContent)
posts_Reviews <- merge(x = posts, y = reviews, by = "artUrl")
# 把文章和topic
posts_Reviews <- merge(x = posts_Reviews, y = mask_topics, by.x = "artUrl", by.y="document")
head(posts_Reviews,3)## artUrl
## 1 https://www.ptt.cc/bbs/Gossiping/M.1621526636.A.DB8.html
## 2 https://www.ptt.cc/bbs/Gossiping/M.1621526636.A.DB8.html
## 3 https://www.ptt.cc/bbs/Gossiping/M.1621526636.A.DB8.html
## artTitle artDate artTime artPoster
## 1 Re:[問卦]你覺得疫情真的跟中共認知作戰有關嗎 2021-05-20 16:03:48 folk0909
## 2 Re:[問卦]你覺得疫情真的跟中共認知作戰有關嗎 2021-05-20 16:03:48 folk0909
## 3 Re:[問卦]你覺得疫情真的跟中共認知作戰有關嗎 2021-05-20 16:03:48 folk0909
## artCat commentNum push boo
## 1 Gossiping 7 1 2
## 2 Gossiping 7 1 2
## 3 Gossiping 7 1 2
## sentence
## 1 這個就是不管民主和獨裁都會用的招\n"內部壓力外部化"\n塑造一個外部的敵人,舒緩內部壓力\n\n舉例來說,去年支那疫情嚴重時,\n中共通過製造外部衝突,塑造出人民的新的敵人,\n那就是台灣,透過不斷的繞台(實際等於對美國挑釁),侵入我們的防空識別區\n,這可以讓中國人不把中共當敵人,並把怒火引導到台灣。\n\n另一個就是美國,在美國疫情嚴重時,\n開始塑造支那這個大敵人,紓解內部對政權防疫不當的壓力\n\n\n\n\n-\nSent from JPTT on my Samsung SM-J730GM.\n
## 2 這個就是不管民主和獨裁都會用的招\n"內部壓力外部化"\n塑造一個外部的敵人,舒緩內部壓力\n\n舉例來說,去年支那疫情嚴重時,\n中共通過製造外部衝突,塑造出人民的新的敵人,\n那就是台灣,透過不斷的繞台(實際等於對美國挑釁),侵入我們的防空識別區\n,這可以讓中國人不把中共當敵人,並把怒火引導到台灣。\n\n另一個就是美國,在美國疫情嚴重時,\n開始塑造支那這個大敵人,紓解內部對政權防疫不當的壓力\n\n\n\n\n-\nSent from JPTT on my Samsung SM-J730GM.\n
## 3 這個就是不管民主和獨裁都會用的招\n"內部壓力外部化"\n塑造一個外部的敵人,舒緩內部壓力\n\n舉例來說,去年支那疫情嚴重時,\n中共通過製造外部衝突,塑造出人民的新的敵人,\n那就是台灣,透過不斷的繞台(實際等於對美國挑釁),侵入我們的防空識別區\n,這可以讓中國人不把中共當敵人,並把怒火引導到台灣。\n\n另一個就是美國,在美國疫情嚴重時,\n開始塑造支那這個大敵人,紓解內部對政權防疫不當的壓力\n\n\n\n\n-\nSent from JPTT on my Samsung SM-J730GM.\n
## cmtPoster cmtStatus cmtContent topic gamma
## 1 NEWOLD 噓 :中共還需要被塑造嗎? 3 0.6648543
## 2 losmith → :所以兩岸一家親手法都一樣... 3 0.6648543
## 3 hunt5566 噓 :安靜 3 0.6648543
取出 cmtPoster(回覆者)、artPoster(發文者)、artUrl(文章連結) 三個欄位
link <- posts_Reviews %>% select(cmtPoster, artPoster, artUrl)
head(link,3)## cmtPoster artPoster artUrl
## 1 NEWOLD folk0909 https://www.ptt.cc/bbs/Gossiping/M.1621526636.A.DB8.html
## 2 losmith folk0909 https://www.ptt.cc/bbs/Gossiping/M.1621526636.A.DB8.html
## 3 hunt5566 folk0909 https://www.ptt.cc/bbs/Gossiping/M.1621526636.A.DB8.html
建立網路關係
reviewNetwork <- graph_from_data_frame(d=link, directed=T)
reviewNetwork## IGRAPH 89c41bc DN-- 15375 56079 --
## + attr: name (v/c), artUrl (e/c)
## + edges from 89c41bc (vertex names):
## [1] NEWOLD ->folk0909 losmith ->folk0909 hunt5566 ->folk0909
## [4] godlikeking->folk0909 godlikeking->folk0909 godlikeking->folk0909
## [7] Fathomeboy ->folk0909 hkcdc ->frankhsu421 npc776 ->frankhsu421
## [10] mijiu ->frankhsu421 ilove640 ->frankhsu421 ilove640 ->frankhsu421
## [13] CCBs ->frankhsu421 KCKCLIN ->frankhsu421 NEWOLD ->frankhsu421
## [16] rock30106 ->frankhsu421 speciallll ->frankhsu421 denyy555 ->frankhsu421
## [19] QBey ->monnom ivorysoap ->monnom ytcytc ->monnom
## [22] AUwalker ->monnom sars7125889->monnom hoanbeh ->monnom
## + ... omitted several edges
直接畫的話,因為點沒有經過篩選,看起來會密密麻麻的 還需要經過一次資料篩選,有興趣可以跑跑下面的code
# 畫出網路圖(密集恐懼警告)
#plot(reviewNetwork)
#plot(reviewNetwork, vertex.size=2, edge.arrow.size=.2,vertex.label=NA)
資料篩選的方式:
# 看一下留言數大概都多少(方便後面篩選)
posts %>%
# filter(commentNum<100) %>%
ggplot(aes(x=commentNum)) + geom_histogram()## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
依據發文數或回覆數篩選post和review
# # 帳號發文篇數
# post_count = posts %>%
# group_by(artPoster) %>%
# summarise(count = n()) %>%
# arrange(desc(count))
# post_count
#
# # 帳號回覆總數
# review_count = reviews %>%
# group_by(cmtPoster) %>%
# summarise(count = n()) %>%
# arrange(desc(count))
# review_count
# # 發文者
# poster_select <- post_count %>% filter(count >= 2)
# posts <- posts %>% filter(posts$artPoster %in% poster_select$artPoster)
#
# # 回覆者
# reviewer_select <- review_count %>% filter(count >= 20)
# reviews <- reviews %>% filter(reviews$cmtPoster %in% reviewer_select$cmtPoster)# 檢視參與人數
length(unique(posts_Reviews$artPoster)) # 發文者數量 1143## [1] 1143
length(unique(posts_Reviews$cmtPoster)) # 回覆者數量 14856## [1] 14856
allPoster <- c(posts_Reviews$artPoster, posts_Reviews$cmtPoster) # 總參與人數 15375
length(unique(allPoster))## [1] 15375
標記所有出現過得使用者
userList <- data.frame(user=unique(allPoster)) %>%
mutate(type=ifelse(user%in%posts$artPoster, "poster", "replyer"))
head(userList,3)## user type
## 1 folk0909 poster
## 2 frankhsu421 poster
## 3 monnom poster
事件是5/22爆發的,我們挑出當天的文章和回覆看看
link <- posts_Reviews %>%
group_by(cmtPoster, artUrl) %>%
filter(n()>3) %>%
filter(commentNum > 200) %>%
filter(artCat=="Gossiping") %>%
filter(artDate == as.Date('2021-05-22')) %>%
select(cmtPoster, artPoster, artUrl) %>%
unique()
link## # A tibble: 383 x 3
## # Groups: cmtPoster, artUrl [383]
## cmtPoster artPoster artUrl
## <chr> <chr> <chr>
## 1 kinomon tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.033.html
## 2 s9234032 tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.033.html
## 3 linkmusic tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.033.html
## 4 menshuei tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.033.html
## 5 imlavender tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.033.html
## 6 a80070 tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.033.html
## 7 kazafso tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.033.html
## 8 ssccg tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.033.html
## 9 scott0104 jiern https://www.ptt.cc/bbs/Gossiping/M.1621649292.A.C4F.html
## 10 hipmyhop b1b2b3b4 https://www.ptt.cc/bbs/Gossiping/M.1621651787.A.44A.html
## # ... with 373 more rows
篩選在link裡面有出現的使用者
filtered_user <- userList %>%
filter(user%in%link$cmtPoster | user%in%link$artPoster) %>%
arrange(desc(type))
head(filtered_user,3)## user type
## 1 KCKCLIN replyer
## 2 kazafso replyer
## 3 tallhigh replyer
這邊要篩選link中有出現的使用者,如果用沒篩過的userList(igraph中graph_from_data_frame的v參數吃的那個東西),圖上就會出現沒有在link裡面的nodes,圖片就會變得沒有意義
p.s.想要看會變怎麼樣的人可以跑下面的code
## 警告!有密集恐懼症的人請小心使用
# v = userList
#reviewNetwork <- graph_from_data_frame(d=link, v=userList, directed=T)
#plot(reviewNetwork, vertex.size=3, edge.arrow.size=0.3,vertex.label=NA)因爲圖片箭頭有點礙眼,所以這裏我們先把關係的方向性拿掉,減少圖片中的不必要的資訊 set.seed 因為igraph呈現的方向是隨機的
set.seed(487)
# v=filtered_user
reviewNetwork = degree(reviewNetwork) > 2
reviewNetwork <- graph_from_data_frame(d=link, v=filtered_user, directed=F)
plot(reviewNetwork, vertex.size=3, edge.arrow.size=0.3,vertex.label=NA)用使用者的身份來區分點的顏色
set.seed(487)
V(reviewNetwork)$color <- ifelse(V(reviewNetwork)$type=="poster", "gold", "lightblue")
plot(reviewNetwork, vertex.size=3, edge.arrow.size=0.3,vertex.label=NA)可以稍微看出圖中的點(人)之間有一定的關聯,不過目前只有單純圖形我們無法分析其中的內容。
因此以下我們將資料集中的資訊加到我們的圖片中。
為點加上帳號名字,用degree篩選要顯示出的使用者,以免圖形被密密麻麻的文字覆蓋
filter_degree = 20
set.seed(123)
# 設定 node 的 label/ color
labels <- degree(reviewNetwork) # 算出每個點的degree
V(reviewNetwork)$label <- names(labels)
V(reviewNetwork)$color <- ifelse(V(reviewNetwork)$type=="poster", "gold", "lightblue")
plot(
reviewNetwork,
vertex.size=3,
edge.width=3,
vertex.label.dist=1,
vertex.label=ifelse(degree(reviewNetwork) > filter_degree, V(reviewNetwork)$label, NA),vertex.label.font=2)我們可以看到基本的使用者關係,但是我們希望能夠將更進階的資訊視覺化。
例如:使用者經常參與的文章種類,或是使用者在該社群網路中是否受到歡迎。
挑選出2021-05-22當天的文章, 篩選一篇文章回覆3次以上者,且文章留言數多餘200則, 文章主題歸類為2(批評調侃)與4(報導相關)者, 欄位只取:cmtPoster(評論者), artPoster(發文者), artUrl(文章連結), topic(主題)
link <- posts_Reviews %>%
group_by(cmtPoster, artUrl) %>%
filter(n()>3) %>%
filter(commentNum > 200) %>%
filter(artCat=="Gossiping") %>% #HatePolitics / Gossiping
filter(artDate == as.Date('2021-05-22')) %>%
# filter(topic == 2 | topic == 4) %>%
select(cmtPoster, artPoster, artUrl, topic) %>%
unique()
link## # A tibble: 383 x 4
## # Groups: cmtPoster, artUrl [383]
## cmtPoster artPoster artUrl topic
## <chr> <chr> <chr> <int>
## 1 kinomon tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.0~ 1
## 2 s9234032 tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.0~ 1
## 3 linkmusic tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.0~ 1
## 4 menshuei tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.0~ 1
## 5 imlavender tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.0~ 1
## 6 a80070 tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.0~ 1
## 7 kazafso tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.0~ 1
## 8 ssccg tibo96033 https://www.ptt.cc/bbs/Gossiping/M.1621648642.A.0~ 1
## 9 scott0104 jiern https://www.ptt.cc/bbs/Gossiping/M.1621649292.A.C~ 1
## 10 hipmyhop b1b2b3b4 https://www.ptt.cc/bbs/Gossiping/M.1621651787.A.4~ 1
## # ... with 373 more rows
filtered_user <- userList %>%
filter(user%in%link$cmtPoster | user%in%link$artPoster) %>%
arrange(desc(type))
head(filtered_user,3)## user type
## 1 KCKCLIN replyer
## 2 kazafso replyer
## 3 tallhigh replyer
filter_degree = 13
# 建立網路關係
reviewNetwork <- graph_from_data_frame(d=link, v=filtered_user, directed=F)
# 依據使用者身份對點進行上色
labels <- degree(reviewNetwork)
V(reviewNetwork)$label <- names(labels)
V(reviewNetwork)$color <- ifelse(V(reviewNetwork)$type=="poster", "gold", "lightblue")
# 依據回覆發生的文章所對應的主題,對他們的關聯線進行上色
E(reviewNetwork)$color <- ifelse(E(reviewNetwork)$topic == "2", "palevioletred", "lightgreen")
# 畫出社群網路圖(degree>7的才畫出來)
set.seed(5432)
plot(reviewNetwork, vertex.size=3, edge.width=3, vertex.label.dist=1,
vertex.label=ifelse(degree(reviewNetwork) > filter_degree, V(reviewNetwork)$label, NA),vertex.label.font=2)
# 加入標示
legend("bottomright", c("發文者","回文者"), pch=21,
col="#777777", pt.bg=c("gold","lightblue"), pt.cex=1, cex=1)
legend("topleft", c("批評調侃","報導相關"),
col=c("palevioletred", "lightgreen"), lty=1, cex=1)PTT的回覆有三種,推文、噓文、箭頭,我們只要看推噓就好,因此把箭頭清掉,這樣資料筆數較少,所以我們把篩選的條件放寬一些。
filter_degree = 7 # 使用者degree
# 過濾留言者對發文者的推噓程度
link <- posts_Reviews %>%
filter(artCat=="Gossiping") %>%
filter(commentNum > 100) %>%
filter(cmtStatus!="→") %>%
group_by(cmtPoster, artUrl) %>%
filter( n() > 2) %>%
ungroup() %>%
select(cmtPoster, artPoster, artUrl, cmtStatus) %>%
unique()
# 接下來把網路圖畫出來,跟前面做的事都一樣,因此不再細述
# 篩選link中有出現的使用者
filtered_user <- userList %>%
filter(user%in%link$cmtPoster | user%in%link$artPoster) %>%
arrange(desc(type))
# 建立網路關係
reviewNetwork <- graph_from_data_frame(d=link, v=filtered_user, directed=F)
# 依據使用者身份對點進行上色
labels <- degree(reviewNetwork)
V(reviewNetwork)$label <- names(labels)
V(reviewNetwork)$color <- ifelse(V(reviewNetwork)$type=="poster", "gold", "lightblue")
# 依據回覆發生的文章所對應的主題,對他們的關聯線進行上色
E(reviewNetwork)$color <- ifelse(E(reviewNetwork)$cmtStatus == "推", "lightgreen", "palevioletred")
# 畫出社群網路圖
set.seed(5432)
plot(reviewNetwork, vertex.size=2, edge.width=3, vertex.label.dist=1,
vertex.label=ifelse(degree(reviewNetwork) > filter_degree, V(reviewNetwork)$label, NA),vertex.label.font=2)
# 加入標示
legend("bottomright", c("發文者","回文者"), pch=21,
col="#777777", pt.bg=c("gold","lightblue"), pt.cex=1, cex=1)
legend("topleft", c("推","噓"),
col=c("lightgreen","palevioletred"), lty=1, cex=1)可以發現本次的討論中幾乎都是推文、噓文較少
需要設定每個節點的id,記得要從0開始
library(networkD3)## Warning: package 'networkD3' was built under R version 4.0.5
links = link
nodes = filtered_user
nodes$id = 0:(length(nodes$user) - 1)
# 整理資料格式
nodes_complete <- data.frame(nodeID = unique(c(links$cmtPoster, links$artPoster)))
nodes_complete$group <- nodes$type[match(nodes_complete$nodeID, nodes$user)]
links$source <- match(links$cmtPoster, nodes_complete$nodeID) - 1
links$target <- match(links$artPoster, nodes_complete$nodeID) - 1
# 畫圖
library(networkD3)
forceNetwork(Links = links, Nodes = nodes_complete, Source = "source",
Target = "target", NodeID = "nodeID", Group = "group",
opacity = 0.8, fontSize = 10, zoom = TRUE,legend = TRUE, opacityNoHover = TRUE,
colourScale = "d3.scaleOrdinal(d3.schemeCategory10);",
linkColour = ifelse(links$cmtStatus == "推", "palegreen","lightcoral") # 設定推噓顏色
)## Links is a tbl_df. Converting to a plain data frame.
校正回歸的討論重點有哪些? 主要分為哪幾種風向? 對於2021-05-21 ~ 2021-05-23收集的文章,大概可以分成嘲諷校正回歸、客觀討論校正回歸這兩種,其他還有著重討論確診個案足跡或和疫苗相關的討論等四種。討論重點多在於統計「數字」、「公布日期」等案例的計算方式。
目前風向最偏哪邊? 客觀討論計算方式的文章不少,但嘲諷、八卦性質的文章居多。
討論校正回歸的社群網路如何分布? 以社群文章數來看,批評嘲諷的網友較多,但從社群網路觀察發現,兩邊的貼文討論聲量都很高。
校正回歸的意見領袖有誰?網友的推噓狀態如何? 因為資料選取的時間較短,只要幾篇回覆量高的貼文,就有機會成為社群中心,在八卦版上,以報導討論為主的意見領袖有 centre0130,回覆推噓皆有,調侃批評部分則有 hstf,網友大多正面推文。
1.畫出政黑板上的社群網路,比較和八卦版上的差異
### Code Here ###以讀書會為單位,針對有興趣的議題分析資料,作業轉成RPubs發布,並將html檔上傳至網大「第十四週HW」,每組一人上傳即可。