!?本文摘自 Shirin's playgRound ! 本文僅為自譯轉(zhuǎn)載杖小,任何觀點(diǎn)都不代表個(gè)人觀點(diǎn)饮焦!
不久之前,我曾經(jīng)做過(guò)一個(gè)關(guān)于冰與火之歌人物關(guān)系的圖譜分析窍侧。在這個(gè)分析中县踢,我發(fā)現(xiàn)史塔克家族(尤其是Ned 和三傻[皮一下很開(kāi)心])和蘭尼斯特家族(尤其是Tyrion),是權(quán)利的游戲中伟件,最主要的家族連接點(diǎn)硼啤。他們連接著很多故事線,也是整個(gè)故事的中心點(diǎn)斧账。
在之前的 PO 文中谴返,我使用了 igraphl 來(lái)描繪和計(jì)算關(guān)系矩陣。
但是現(xiàn)在有兩個(gè)更好的包可以完成整個(gè)關(guān)系分析:?tidyverse:?tidygraph?和?ggraph咧织。
所以這篇文章將使用這兩個(gè)包來(lái)制作 冰與火之歌/權(quán)利的游戲 的任務(wù)關(guān)系分析圖嗓袱。(內(nèi)容基于冰與火這個(gè)著作而非電視節(jié)目)
社會(huì)關(guān)系分析 或者社會(huì)網(wǎng)絡(luò)分析能帶來(lái)什么?
關(guān)系分析能發(fā)現(xiàn)和挖掘社會(huì)或者專(zhuān)業(yè)領(lǐng)域社交網(wǎng)絡(luò)中的關(guān)系习绢。我們通常會(huì)問(wèn):每個(gè)網(wǎng)絡(luò)中的人(節(jié)點(diǎn))有多少關(guān)系連接(邊)渠抹?
誰(shuí)是連接數(shù)最多(最重要,最有影響力)的人闪萄?
緊密聯(lián)系的人是否導(dǎo)致大的集群的存在梧却?
是否有關(guān)鍵人物在集群之間擁有重要作用?
這些問(wèn)題的答案通嘲苋ィ可以幫助我們理解放航,人類(lèi)是怎么在社會(huì)中交流和互動(dòng)。
所以圆裕,我們?cè)趺床拍苷业皆诰W(wǎng)絡(luò)中最重要的角色广鳍?簡(jiǎn)單來(lái)說(shuō),當(dāng)一個(gè)人擁有最多關(guān)系或最多與之相連的人的時(shí)候吓妆,其重要性不言則明赊时。同時(shí)也有一些其他的屬性可以幫助我們尋找這些關(guān)鍵人物,例如節(jié)點(diǎn)中心度(node centrality).
冰與火之歌角色關(guān)系圖
library(readr)? ???# fast reading of csv files
library(tidyverse) # tidy data analysis
library(tidygraph) # tidy graph analysis
library(ggraph)? ? # for plotting
數(shù)據(jù)
數(shù)據(jù)來(lái)源于 Github Repository耿战,Andrew Beveridge:
Character Interaction Networks for George R. R. Martin’s “A Song of Ice and Fire” saga These networks were created by connecting two characters whenever their names (or nicknames) appeared within 15 words of one another in one of the books in “A Song of Ice and Fire.” The edge weight corresponds to the number of interactions. You can use this data to explore the dynamics of the Seven Kingdoms using network science techniques. For example, community detection finds coherent plotlines. Centrality measures uncover the multiple ways in which characters play important roles in the saga.
Andrew 已經(jīng)做過(guò)一個(gè)關(guān)于冰與火之歌角色關(guān)系的分析蛋叼,如果你感興趣焊傅,也可以去他的網(wǎng)站瀏覽他的結(jié)論https://networkofthrones.wordpress.com
這里我不想復(fù)制他的分析剂陡,而是希望展示如何使用 tidygraph 和 ggraph狈涮。所以我并不會(huì)完全使用他的數(shù)據(jù)。
path <- "/Users/shiringlander/Documents/Github/Data/asoiaf/data/"
files <- list.files(path = path, full.names = TRUE)
files
##??[1] "/Users/shiringlander/Documents/Github/Data/asoiaf/data//asoiaf-all-edges.csv"
##??[2] "/Users/shiringlander/Documents/Github/Data/asoiaf/data//asoiaf-all-nodes.csv"
##??[3] "/Users/shiringlander/Documents/Github/Data/asoiaf/data//asoiaf-book1-edges.csv"?
##??[4] "/Users/shiringlander/Documents/Github/Data/asoiaf/data//asoiaf-book1-nodes.csv"?
##??[5] "/Users/shiringlander/Documents/Github/Data/asoiaf/data//asoiaf-book2-edges.csv"?
##??[6] "/Users/shiringlander/Documents/Github/Data/asoiaf/data//asoiaf-book2-nodes.csv"?
##??[7] "/Users/shiringlander/Documents/Github/Data/asoiaf/data//asoiaf-book3-edges.csv"?
##??[8] "/Users/shiringlander/Documents/Github/Data/asoiaf/data//asoiaf-book3-nodes.csv"?
##??[9] "/Users/shiringlander/Documents/Github/Data/asoiaf/data//asoiaf-book4-edges.csv"?
## [10] "/Users/shiringlander/Documents/Github/Data/asoiaf/data//asoiaf-book4-nodes.csv"?
## [11] "/Users/shiringlander/Documents/Github/Data/asoiaf/data//asoiaf-book45-edges.csv"
## [12] "/Users/shiringlander/Documents/Github/Data/asoiaf/data//asoiaf-book45-nodes.csv"
## [13] "/Users/shiringlander/Documents/Github/Data/asoiaf/data//asoiaf-book5-edges.csv"?
## [14] "/Users/shiringlander/Documents/Github/Data/asoiaf/data//asoiaf-book5-nodes.csv"
全書(shū)角色
首先要使用的是全書(shū)角色互動(dòng)關(guān)系的數(shù)據(jù)鸭栖。這里我不打算使用節(jié)點(diǎn)的數(shù)據(jù)歌馍,因?yàn)槲野l(fā)現(xiàn)關(guān)系(edge)的名稱(chēng)標(biāo)記已經(jīng)足夠用來(lái)標(biāo)注。當(dāng)然晕鹊,如果你希望使用更好的名詞標(biāo)識(shí)松却,可以使用節(jié)點(diǎn)數(shù)據(jù)。
cooc_all_edges <- read_csv(files[1])
因?yàn)闀?shū)中有太多角色溅话,而且很多都是小角色晓锻,所以我抽出前100位互動(dòng)關(guān)系較多的角色。關(guān)系都是無(wú)向關(guān)系飞几,所以沒(méi)有冗余的Source-Target combination
main_ch <- cooc_all_edges %>%
select(-Type) %>%
gather(x, name, Source:Target) %>%
group_by(name) %>%
summarise(sum_weight = sum(weight)) %>%
ungroup()
main_ch_l <- main_ch %>%
arrange(desc(sum_weight)) %>%
top_n(100, sum_weight)
main_ch_l
## # A tibble: 100 x 2
##? ? name? ?? ?? ?? ?? ?sum_weight
##
##??1 Tyrion-Lannister? ?? ?? ?2873
##??2 Jon-Snow? ?? ?? ?? ?? ???2757
##??3 Cersei-Lannister? ?? ?? ?2232
##??4 Joffrey-Baratheon? ?? ???1762
##??5 Eddard-Stark? ?? ?? ?? ? 1649
##??6 Daenerys-Targaryen? ?? ? 1608
##??7 Jaime-Lannister? ?? ?? ? 1569
##??8 Sansa-Stark? ?? ?? ?? ???1547
##??9 Bran-Stark? ?? ?? ?? ?? ?1508
## 10 Robert-Baratheon? ?? ?? ?1488
## # ... with 90 more rows
cooc_all_f <- cooc_all_edges %>%
filter(Source %in% main_ch_l$name & Target %in% main_ch_l$name)
tidygraph 和 ggraph
兩個(gè)工具包都來(lái)自于?Thomas Lin Pedersen:
With tidygraph I set out to make it easier to get your data into a graph and perform common transformations on it, but the aim has expanded since its inception. The goal of tidygraph is to empower the user to formulate complex questions regarding relational data as simple steps, thus enabling them to retrieve insights directly from the data itself. The central idea this all boils down to is this: you don’t have to plot a network to understand it. While I absolutely love the field of network visualisation, it is in many ways overused in data science — especially when it comes to extracting knowledge from a network. Just as you don’t need a plot to tell you which car in a dataset is the fastest, you don’t need a plot to tell you which pair of friends are the closest. What you do need, instead of a plot, is a tool that allow you to formulate your question into a logic sequence of operations. For many people in the world of rectangular data, this tool is increasingly dplyr (and friends), and I do hope that tidygraph can take on the same role in the world of relational data.?https://www.data-imaginist.com/2018/tidygraph-1-1-a-tidy-hope/
首先砚哆,將邊的表格轉(zhuǎn)換為 tbl_graph 格式。這里使用 tidygrpah 中的as_tbl_graph()函數(shù)屑墨,其可以輸入 data.frame,matrix,dendrogram,igraph,etc.
Underneath the hood of tidygraph lies the well-oiled machinery of igraph, ensuring efficient graph manipulation. Rather than keeping the node and edge data in a list and creating igraph objects on the fly when needed, tidygraph subclasses igraph with the tbl_graph class and simply exposes it in a tidy manner. This ensures that all your beloved algorithms that expects igraph objects still works with tbl_graph objects. Further, tidygraph is very careful not to override any of igraphs exports so the two packages can coexist quite happily.?https://www.data-imaginist.com/2018/tidygraph-1-1-a-tidy-hope/
有很多 node ranking 的選擇(可以去?node_rank查看詳細(xì)列表)躁锁。我這里嘗試TSP 解算器最小化哈密頓回路的方法?Minimize hamiltonian path length using a travelling salesperson solver):
as_tbl_graph(cooc_all_f, directed = FALSE) %>%
activate(nodes) %>%?
mutate(n_rank_trv = node_rank_traveller()) %>%
arrange(n_rank_trv)
## # A tbl_graph: 100 nodes and 798 edges
## #
## # An undirected simple graph with 1 component
## #
## # Node Data: 100 x 2 (active)
##? ?name? ?? ?? ?? ?? ?? ?? ?? ?? ? n_rank_trv
##
## 1 Janos-Slynt? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?1
## 2 Aemon-Targaryen-(Maester-Aemon)? ?? ?? ? 2
## 3 Jeor-Mormont? ?? ?? ?? ?? ?? ?? ?? ?? ???3
## 4 Samwell-Tarly? ?? ?? ?? ?? ?? ?? ?? ?? ? 4
## 5 Qhorin-Halfhand? ?? ?? ?? ?? ?? ?? ?? ???5
## 6 Ygritte? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? 6
## # ... with 94 more rows
## #
## # Edge Data: 798 x 5
##? ? from? ? to Type? ?? ?? ? id weight
##?
## 1? ???2? ? 75 Undirected? ? 43? ?? ?7
## 2? ???2? ? 76 Undirected? ? 44? ?? ?4
## 3? ???2? ? 73 Undirected? ? 52? ?? ?3
## # ... with 795 more rows
Centrality 中心度
中心度用來(lái)表示節(jié)點(diǎn)入度和出度的數(shù)量。高度中心化的網(wǎng)絡(luò)中卵史,且之有較少的節(jié)點(diǎn)擁有較大數(shù)量的邊战转。低度中心化的網(wǎng)絡(luò)中擁有較多的節(jié)點(diǎn),同時(shí)節(jié)點(diǎn)度相對(duì)小而平均以躯。而節(jié)點(diǎn)中心度衡量了節(jié)點(diǎn)在網(wǎng)絡(luò)中的重要程度槐秧。
This version adds 19(!) new ways to define the notion of centrality along with a manual version where you can mix and match different distance measures and summation strategies opening up the world to even more centrality scores. All of this wealth of centrality comes from the netrankr package that provides a framework for defining and calculating centrality scores. If you use centrality measures somewhere in your analysis I cannot recommend the vignettes provided by netrankr enough as they provide a fundamental intuition about the nature of such measures and how they can/should be used.?https://www.data-imaginist.com/2018/tidygraph-1-1-a-tidy-hope/
可以使用?centrality查看所有關(guān)于中心度計(jì)算的所有方法。 這里我們使用centrality_degree()忧设。
## # A tbl_graph: 100 nodes and 798 edges
## #
## # An undirected simple graph with 1 component
## #
## # Node Data: 100 x 2 (active)
##? ?name? ?? ?? ?? ???neighbors
##
## 1 Tyrion-Lannister? ?? ???54.
## 2 Cersei-Lannister? ?? ???49.
## 3 Joffrey-Baratheon? ?? ? 49.
## 4 Robert-Baratheon? ?? ???47.
## 5 Jaime-Lannister? ?? ?? ?45.
## 6 Sansa-Stark? ?? ?? ?? ? 44.
## # ... with 94 more rows
## #
## # Edge Data: 798 x 5
##? ? from? ? to Type? ?? ?? ? id weight
##?
## 1? ? 41? ? 42 Undirected? ? 43? ?? ?7
## 2? ? 41? ? 60 Undirected? ? 44? ?? ?4
## 3? ? 41? ? 63 Undirected? ? 52? ?? ?3
## # ... with 795 more rows
組和聚類(lèi) Grouping and clustring
Another common operation is to group nodes based on the graph topology, sometimes referred to as community detection based on its commonality in social network analysis. All clustering algorithms from igraph is available in tidygraph using the group_* prefix. All of these functions return an integer vector with nodes (or edges) sharing the same integer being grouped together. https://www.data-imaginist.com/2017/introducing-tidygraph/
可以使用?group_graph查看所有分組和聚類(lèi)的方法色鸳。這里我使用 group_infomap():Group nodes by minimizing description length using.
as_tbl_graph(cooc_all_f, directed = FALSE) %>%
activate(nodes) %>%?
mutate(group = group_infomap()) %>%
arrange(-group)
## # A tbl_graph: 100 nodes and 798 edges
## #
## # An undirected simple graph with 1 component
## #
## # Node Data: 100 x 2 (active)
##? ?name? ?? ?? ?? ???group
##?
## 1 Arianne-Martell? ?? ? 7
## 2 Doran-Martell? ?? ?? ?7
## 3 Davos-Seaworth? ?? ???6
## 4 Melisandre? ?? ?? ?? ?6
## 5 Selyse-Florent? ?? ???6
## 6 Stannis-Baratheon? ???6
## # ... with 94 more rows
## #
## # Edge Data: 798 x 5
##? ? from? ? to Type? ?? ?? ? id weight
##?
## 1? ? 32? ? 33 Undirected? ? 43? ?? ?7
## 2? ? 32? ? 34 Undirected? ? 44? ?? ?4
## 3? ? 32? ? 36 Undirected? ? 52? ?? ?3
## # ... with 795 more rows
復(fù)制代碼
查詢(xún)節(jié)點(diǎn)類(lèi)型(query node type)
我們也可以查詢(xún)節(jié)點(diǎn)類(lèi)型,使用?node_types 來(lái)查看所有內(nèi)容见转。
These functions all lets the user query whether each node is of a certain type. All of the functions returns a logical vector indicating whether the node is of the type in question. Do note that the types are not mutually exclusive and that nodes can thus be of multiple types.
這里我使用 node_is_center 和 node_is_keyplayer 來(lái)查詢(xún)圖中前10名重要關(guān)鍵人物命雀。 你也可以在 influenceR 包中找到更多關(guān)于 node_is_keyplayer 函數(shù)的內(nèi)容。
The “Key Player” family of node importance algorithms (Borgatti 2006) involves the selection of a metric of node importance and a combinatorial optimization strategy to choose the set S of vertices of size k that maximize that metric. This function implements KPP-Pos, a metric intended to identify k nodes which optimize resource diffusion through the net … https://www.data-imaginist.com/2017/introducing-tidygraph/
as_tbl_graph(cooc_all_f, directed = FALSE) %>%
activate(nodes) %>%?
mutate(dist_to_center = node_distance_to(node_is_center()))
## # A tbl_graph: 100 nodes and 798 edges
## #
## # An undirected simple graph with 1 component
## #
## # Node Data: 100 x 2 (active)
##? ?name? ?? ?? ?? ?? ?? ?? ?? ?? ? dist_to_center
##
## 1 Aemon-Targaryen-(Maester-Aemon)? ?? ?? ?? ? 1.
## 2 Aeron-Greyjoy? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? 2.
## 3 Aerys-II-Targaryen? ?? ?? ?? ?? ?? ?? ?? ???1.
## 4 Alliser-Thorne? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?1.
## 5 Arianne-Martell? ?? ?? ?? ?? ?? ?? ?? ?? ???2.
## 6 Arya-Stark? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? 1.
## # ... with 94 more rows
## #
## # Edge Data: 798 x 5
##? ? from? ? to Type? ?? ?? ? id weight
##?
## 1? ???1? ???4 Undirected? ? 43? ?? ?7
## 2? ???1? ? 13 Undirected? ? 44? ?? ?4
## 3? ???1? ? 28 Undirected? ? 52? ?? ?3
## # ... with 795 more rows
復(fù)制代碼
Edge betweeness
和節(jié)點(diǎn)的指標(biāo)一樣斩箫,邊或者關(guān)系上吏砂,我們也可以獲得很多指標(biāo)。Betweeness 就是用來(lái)表示任意兩個(gè)節(jié)點(diǎn)間最短路徑的關(guān)系指標(biāo)乘客。[皮一下:小世界理論狐血?]。tidygraph 中可以查看edge_type的詳細(xì)內(nèi)容
as_tbl_graph(cooc_all_f, directed = FALSE) %>%
activate(edges) %>%?
mutate(centrality_e = centrality_edge_betweenness())
## # A tbl_graph: 100 nodes and 798 edges
## #
## # An undirected simple graph with 1 component
## #
## # Edge Data: 798 x 6 (active)
##? ? from? ? to Type? ?? ?? ? id weight centrality_e
##
## 1? ???1? ???4 Undirected? ? 43? ?? ?7? ?? ?? ?1.00
## 2? ???1? ? 13 Undirected? ? 44? ?? ?4? ?? ???30.2?
## 3? ???1? ? 28 Undirected? ? 52? ?? ?3? ?? ???42.1?
## 4? ???1? ? 32 Undirected? ? 53? ???20? ?? ?? ?0.
## 5? ???1? ? 34 Undirected? ? 54? ?? ?5? ?? ???35.2?
## 6? ???1? ? 41 Undirected? ? 56? ?? ?5? ?? ???18.9?
## # ... with 792 more rows
## #
## # Node Data: 100 x 1
##? ?name
##
## 1 Aemon-Targaryen-(Maester-Aemon)
## 2 Aeron-Greyjoy
## 3 Aerys-II-Targaryen?
## # ... with 97 more rows
復(fù)制代碼
完整的內(nèi)容
讓我們組合起來(lái)之前的東西:
cooc_all_f_graph <- as_tbl_graph(cooc_all_f, directed = FALSE) %>%
mutate(n_rank_trv = node_rank_traveller(),
neighbors = centrality_degree(),
group = group_infomap(),
center = node_is_center(),
dist_to_center = node_distance_to(node_is_center()),
keyplayer = node_is_keyplayer(k = 10)) %>%
activate(edges) %>%?
filter(!edge_is_multiple()) %>%
??mutate(centrality_e = centrality_edge_betweenness())
復(fù)制代碼
我們也可以將節(jié)點(diǎn)和邊的表轉(zhuǎn)換為tibble:
cooc_all_f_graph %>%
activate(nodes) %>% # %N>%
as.tibble()
## # A tibble: 100 x 7
##? ? name? ?? ?? ?n_rank_trv neighbors group center dist_to_center keyplayer
##?
##??1 Aemon-Targa…? ?? ?? ?45? ?? ? 13.? ???2 FALSE? ?? ?? ?? ???1. FALSE?
##??2 Aeron-Greyj…? ?? ?? ?21? ?? ???5.? ???5 FALSE? ?? ?? ?? ???2. FALSE?
##??3 Aerys-II-Ta…? ?? ?? ?11? ?? ? 12.? ???1 FALSE? ?? ?? ?? ???1. FALSE?
##??4 Alliser-Tho…? ?? ?? ?48? ?? ? 13.? ???2 FALSE? ?? ?? ?? ???1. FALSE?
##??5 Arianne-Mar…? ?? ?? ?29? ?? ???4.? ???7 FALSE? ?? ?? ?? ???2. FALSE?
##??6 Arya-Stark? ?? ?? ???79? ?? ? 37.? ???1 FALSE? ?? ?? ?? ???1. FALSE?
##??7 Asha-Greyjoy? ?? ?? ?20? ?? ???7.? ???5 FALSE? ?? ?? ?? ???1. FALSE?
##??8 Balon-Greyj…? ?? ?? ?18? ?? ? 11.? ???5 FALSE? ?? ?? ?? ???2. FALSE?
##??9 Barristan-S…? ?? ?? ?54? ?? ? 23.? ???3 FALSE? ?? ?? ?? ???1. FALSE?
## 10 Belwas? ?? ?? ?? ?? ?52? ?? ???6.? ???3 FALSE? ?? ?? ?? ???2. FALSE?
## # ... with 90 more rows
cooc_all_f_graph %>%
activate(edges) %>% # %E>%
as.tibble()
## # A tibble: 798 x 6
##? ???from? ? to Type? ?? ?? ? id weight centrality_e
##?
##??1? ???1? ???4 Undirected? ? 43? ?? ?7? ?? ?? ?1.00
##??2? ???1? ? 13 Undirected? ? 44? ?? ?4? ?? ???30.2?
##??3? ???1? ? 28 Undirected? ? 52? ?? ?3? ?? ???42.1?
##??4? ???1? ? 32 Undirected? ? 53? ???20? ?? ?? ?0.
##??5? ???1? ? 34 Undirected? ? 54? ?? ?5? ?? ???35.2?
##??6? ???1? ? 41 Undirected? ? 56? ?? ?5? ?? ???18.9?
##??7? ???1? ? 42 Undirected? ? 57? ???25? ?? ?? ?0.
##??8? ???1? ? 48 Undirected? ? 58? ? 110? ?? ?? ?0.
##??9? ???1? ? 58 Undirected? ? 60? ?? ?5? ?? ???24.5?
## 10? ???1? ? 71 Undirected? ? 62? ?? ?5? ?? ???17.0?
## # ... with 788 more rows
復(fù)制代碼
ggraph 畫(huà)圖
ggraph is an extension of ggplot2 aimed at supporting relational data structures such as networks, graphs, and trees. While it builds upon the foundation of ggplot2 and its API it comes with its own self-contained set of geoms, facets, etc., as well as adding the concept of layouts to the grammar. https://github.com/thomasp85/ggraph
首先易核,我需要定義 一層 layout, 有很多 options for layout,這里我要使用?Fruchterman-Reingold?algorithm匈织。
layout <- create_layout(cooc_all_f_graph,?
? ?? ?? ?? ?? ?? ?? ?? ?layout = "fr")
復(fù)制代碼
剩下的工作就比較類(lèi)似于 ggplot2的函數(shù),只不過(guò)我們會(huì)用到特殊的函數(shù)來(lái)繪制網(wǎng)絡(luò)。比如 geom_edge_density 可以用來(lái)畫(huà)高密度的陰影區(qū)域缀匕,geom_edge_lin 來(lái)連接節(jié)點(diǎn)纳决,geom_node_point 來(lái)繪制節(jié)點(diǎn),同時(shí) geom_node_text 用來(lái)標(biāo)注節(jié)點(diǎn)名稱(chēng)乡小。 你也可以在手冊(cè)中找到更詳細(xì)的內(nèi)容阔加。
graph(layout) +?
geom_edge_density(aes(fill = weight)) +
geom_edge_link(aes(width = weight), alpha = 0.2) +?
geom_node_point(aes(color = factor(group)), size = 10) +
geom_node_text(aes(label = name), size = 8, repel = TRUE) +
scale_color_brewer(palette = "Set1") +
theme_graph() +
labs(title = "A Song of Ice and Fire character network",
? ?? ?? ?subtitle = "Nodes are colored by group")
復(fù)制代碼
Interestingly, many of the groups reflect the narrative perfectly: the men from the Night’s Watch are grouped together with the Wildlings, Stannis, Davos, Selyse and Melisandre form another group, the Greyjoys, Bran’s group in Winterfell before they left for the North, Dany and her squad and the Martells (except for Quentyn, who “belongs” to Dany – just like in the books ;-)). The big group around the remaining characters is the only one that’s not split up very well.
下圖使用了?RColorBrewer?palette “Set1”:
該圖中我畫(huà)出了最中心的人物,同時(shí)節(jié)點(diǎn)的大小表示各個(gè)節(jié)點(diǎn)到中心的距離满钟。書(shū)中最重要的兩個(gè)角色就是Robert 和 Tyrion. (馬丁大爺反正說(shuō)他最喜歡小惡魔【笑】)
各個(gè)書(shū)中的角色
后面該作者也做了各個(gè)書(shū)中的角色的網(wǎng)絡(luò)圖胜榔。
The second data set I am going to use is a comparison of character interactions in the five books.
A little node on the side:?My original plan was to loop over the separate edge files for each book, concatenate them together with the information from which book they are and then plot them via faceting. This turned out to be a bad solution because I wanted to show the different key-players in each of the five books. So, instead of using one joined graph, I created separate graphs for every book and used the bind_graphs() and facet_nodes() functions to plot them together.
for (i in 1:5) {
cooc <- read_csv(paste0("/Users/shiringlander/Documents/Github/Data/asoiaf/data//asoiaf-book", i, "-edges.csv")) %>%
mutate(book = paste0("book_", i)) %>%
filter(Source %in% main_ch_l$name & Target %in% main_ch_l$name)
assign(paste0("coocs_book_", i), cooc)
}
The concepts are the same as above, here I want to know the key-players in each book:
cooc_books_1_graph <- as_tbl_graph(coocs_book_1, directed = FALSE) %>%
mutate(book = "Book 1: A Game of Thrones",
keyplayer = node_is_keyplayer(k = 10))
cooc_books_2_graph <- as_tbl_graph(coocs_book_2, directed = FALSE) %>%
mutate(book = "Book 2: A Clash of Kings",
keyplayer = node_is_keyplayer(k = 10))
cooc_books_3_graph <- as_tbl_graph(coocs_book_3, directed = FALSE) %>%
mutate(book = "Book 3: A Storm of Swords",
keyplayer = node_is_keyplayer(k = 10))
cooc_books_4_graph <- as_tbl_graph(coocs_book_4, directed = FALSE) %>%
mutate(book = "Book 4: A Feast for Crows",
keyplayer = node_is_keyplayer(k = 10))
cooc_books_5_graph <- as_tbl_graph(coocs_book_5, directed = FALSE) %>%
mutate(book = "Book 5: A Dance with Dragons",
keyplayer = node_is_keyplayer(k = 10))
And let’s combine and plot the key-players:
cooc_books_1_graph %>%?
bind_graphs(cooc_books_2_graph)??%>%
bind_graphs(cooc_books_3_graph)??%>%
bind_graphs(cooc_books_4_graph)??%>%
bind_graphs(cooc_books_5_graph)??%>%
ggraph(layout = "fr") +?
facet_nodes( ~ book, scales = "free", ncol = 1) +
geom_edge_density(aes(fill = weight)) +
geom_edge_link(aes(edge_width = weight), alpha = 0.2) +?
geom_node_point(aes(color = factor(keyplayer)), size = 3) +
geom_node_text(aes(label = name), color = "black", size = 3, repel = TRUE) +
theme_graph() +
? ? scale_colour_manual(values = c(cols[2], cols[1]))
復(fù)制代碼
全文摘自: https://www.r-bloggers.com/another-game-of-thrones-network-analysis-this-time-with-tidygraph-and-ggraph/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+RBloggers+%28R+bloggers%29
作者:?Dr. Shirin Glander
僅做分享討論
:)