如何用 R 繪制交互式社會網絡圖?

挖掘社會關系網絡,助你洞若觀火。

需求

最近有個學生問我,如何繪制交互式社會網絡圖(Interactive Social Network Graph)?

之所以一定要交互式,是因為他的應用場景,是演示給客戶。

他解釋說,如果客戶有選項,可以根據需要來縮放圖形、聚焦類別,甚至是可以拖拽圖形元素,以不同視角來查看,那展示效果顯然會更好。

我對學生這次把握客戶需求的能力,還是比較贊賞的。確實,數據可視化的目的就是為了與人溝通。而人是需要控制感的。

在數據科學里,這個需求,屬于網絡可視化(Network Visualization)范疇。應用上,除了描繪社會網絡外,這種可視化的對象還可以包括引文網絡、貿易網絡、信息(或疾?。﹤鞑ゾW絡等。甚至,網絡可視化操作還能與時序數據結合,例如 Maximilian Noichl 繪制的這張古代哲學家的動態(tài)關系網絡圖。

網絡可視化的工具,是非常多的。

然而,一旦涉及了交互式,選項就大幅減少了。特別是,他還要求免費、易學格式開放、演示環(huán)境易于部署……

這條件,夠苛刻了吧?

還好,我還真就幫他找到了。

雖然易學,可是由于他是文科生,我覺得還是給他寫個教程,比較妥帖。

教程寫完之后,我覺得你可能也會用得上,所以一并分享給你。

演示數據,我自然不能用他的。否則有泄露商業(yè)機密的風險。這里我采用的,是斯坦福大學開放課程《數據庫基礎》中的一個簡單數據樣例。我在國際班講的英文數據庫課程,一直用它作為練習數據。

這個演示數據的特點,就是簡單。

有多簡單?往下看。

數據

該數據刻畫的,是某高中里4個年級部分學生之間的社交關系。

我們一共需要用到3張數據表格,分別是學生信息、朋友關系和“喜歡”關系。

先看學生信息表。我已經把它上傳到了這個 github 鏈接,你可以點擊查看。

表格包含3列,分別是學號、姓名和年級。

然后是朋友關系表。請點擊這個鏈接查看。

除去表頭,一共20行。包含兩列,代表了關系兩端的兩個學生的學號。

注意“朋友”關系是一種雙向(或者無向)關系。兩個人都認可的,才算是朋友。我在人群中,一眼就能認出某影視巨星。可惜,人家不認識我,這顯然就不算朋友關系。

再后面,是“喜歡”(likes)關系表。我放在了這個鏈接

注意這里雖然也描述了關系的起點和終點,但是“喜歡”關系是一種有向關系。張三喜歡李四,李四可能并不喜歡張三。

好了,這就是我們需要用到的全部數據了。下面我們來看看運行環(huán)境。

環(huán)境

我們使用的,是 R 的集成開發(fā)環(huán)境(integrated development environment, IDE) RStudio 。

你可以在本機安裝 R 以及 RStudio 。我已經把安裝和設置步驟寫在了《如何用 R 快速了解科研領域?》一文中。

配套的代碼和數據,我放在了這個 github 倉庫中。你可以下載使用。

然而,此處為了你更快捷地上手,我直接為你準備了云端的運行環(huán)境。你只需要點擊這個鏈接http://t.cn/EJ5U8o6),就可以直接在瀏覽器里面開啟一個 RStudio 。其中,已包含了我為你準備好的數據和代碼。

雙擊右下方目錄區(qū)域里面的 demo.Rmd,你就能看到對應的筆記本了。

怎么樣?夠方便吧?

其實,你自己也可以構建這樣的云端環(huán)境。具體的方法,我已經在《如何用iPad運行Python代碼?》一文中為你詳細介紹了。如果你感興趣,可以在學過本篇教程后,嘗試練練手。

下面我們開始介紹代碼了。請你根據我的介紹,逐步點擊代碼模塊旁邊的運行按鈕,查看運行的結果。

代碼

首先,我們需要讀入本教程中最重要的軟件包,也就是 R 環(huán)境下的網絡交互可視化工具—— visNetwork。

visNetwork 基于 Javascript 可視化工具庫 vis.js 開發(fā),為 R 用戶提供了簡單易用的界面,而且功能也很強大。

我們使用 library 命令來讀入它。

library('visNetwork')

下面我們來讀入數據。

首先,我們觀察“朋友”關系。讀入學生信息表和朋友關系表。

nodes <- read.csv("data/Highschooler.csv", header=T, as.is=T)
friends <- read.csv("data/Friend.csv", header=T, as.is=T)

注意這里的參數:

  • header=T 是指我們讀入的數據里包含了表頭,需要讓 R 注意,不要把表頭也當成了數據來處理;
  • as.is=T 是指讀入的字符串數據,不要默認按照因子來轉換。這其實是一種技巧。因為如果大量數據默認做轉換,可能會導致讀取效率很低。當然,對于我們的例子來說,因為數據量很小,實際上效率差別不大。但是好習慣還是需要養(yǎng)成的。

下面我們要在節(jié)點上生成一些屬性。我們希望把鼠標挪到某個節(jié)點上的時候,顯示該學生屬于“某年級”;而生成圖像的時候,直接在節(jié)點旁邊標明學生的姓名。

因此,我們就需要分別對 nodes$titlenodes$label 賦值。

之后,用 visNetwork 可視化我們的節(jié)點和關系連線。

nodes$title <- paste0("grade", nodes$grade)
nodes$label <- nodes$name
visNetwork(nodes, friends)

結果如下圖所示:

注意,這可不是一張靜態(tài)圖,你把鼠標懸浮到 Alexis 人名上試試看。

年級屬性就出現了。

你還可以拖動任意一個學生節(jié)點,感受一下什么叫做“牽一發(fā)而動全身”。

有趣吧?

但是現在所有的節(jié)點,都是一樣的顏色。我們希望依據不同的年級,重新繪制節(jié)點顏色,這樣看得會更清晰。

我們依據年級屬性(nodes$grade),來定義節(jié)點的背景顏色(nodes$color.background)。

然后再次調用 visNetwork,進行繪制。

nodes$color.background <- c("orange", "pink", "yellow", "blue")[nodes$grade]
visNetwork(nodes, friends)

結果是……

不對呀,說好的顏色變化呢?

別著急。

如果讓 R 根據不同屬性來區(qū)分顏色,我們首先需要保證該屬性類型是因子(factor)。可是我們讀取的時候,為了效率,沒讓 R 自動轉換。

怎么辦?

手動來做吧。

nodes$grade <- as.factor(nodes$grade)
nodes$color.background <- c("orange", "pink", "yellow", "blue")[nodes$grade]
visNetwork(nodes, friends)

這次,我們再看看結果:

嗯,感覺好極了。

這里節(jié)點很少,全部同時顯示,也能看得清晰。但是假設我們需要處理一所真正學校中的朋友關系,可以想象那會有成百上千個節(jié)點。如果我們希望聚焦,那就得給用戶更多的交互功能。

這里我給你介紹其中一個選項,就是利用 selectedBy ,指定我們讓用戶在哪一個屬性上進行分組選擇。

你需要把它放在 visOptions 中。

visNetwork(nodes, friends) %>%
  visOptions(selectedBy = "grade")

運行效果是這樣的:

看起來,跟剛剛區(qū)別不大,只是多了一個下拉框而已。

我們嘗試選擇一下:

交互選項,讓當前分組保持高亮,其他分組變灰暗,于是我們的注意力就可以集中。

嘗試著玩兒一下,看看你能否發(fā)現什么有趣的關系模式?

我發(fā)現了一個。

大部分情況下,同一個年級的學生間,總會可以關聯(lián)起來。但是,11年級的 Austin ,跟本年級的其他3名同學,沒有任何直接聯(lián)系。反而,跟其他年級的學生,保持了朋友關系。

如果你是他的班主任,要不要關注一下?

下面,我們來看看另外一種關系——“喜歡”(likes)。

還是讀入 csv 文件,到 likes 數據框里面。參數跟剛才一樣。

likes <- read.csv("data/Likes.csv", header=T, as.is=T)

先來繪制看看。

visNetwork(nodes, likes)

我們一下子就發(fā)現了,這次的整體圖形,不再是全連通的。出現了孤立節(jié)點。

這些人,既沒有“喜歡”別人,也沒有“被喜歡”。你自己找找看,都包括哪幾個學生?

注意這個圖形,是有問題的。

前面提到過,“喜歡”關系是一種有向關系。因此關系的方向很重要。但是目前這張圖里面,方向是缺失的。

沒關系,只需要給 likes 加入一個屬性 arrow 就好。

likes$arrows <- "to"
visNetwork(nodes, likes)

這次就對了。

下面我們來玩兒一個更有趣的——把兩個關系合并,一起觀察。

我們需要記錄一下,關系來自于哪張關系表格。所以分別把表名稱作為屬性,填到 relation 字段中。

friends$relation <- c("friend")
likes$relation <- c("likes")

看看這時候的 friends 朋友關系表。

friends

好了,下面我們需要合并兩張表格。我們需要用到 tidyverse 軟件包中的按行合并(bind_rows)功能。所以,需要首先載入tidyverse 軟件包。

library(tidyverse)

然后,把原先的兩張關系表,合并成一張,起名叫做 links 。

links <- bind_rows(friends, likes)
links

再次繪制,注意這次,關系位置上,我們放的是合并的 links 。

visNetwork(nodes, links)

兩種關系,確實都繪制好了。可問題是,關系展示的顏色是一樣的藍色,看著不是很清晰。

仿照剛才對節(jié)點的顏色賦值,我們把關系連接的顏色也設置一下。

links$color <- c("green", "red")[links$relation]
visNetwork(nodes, links)

呃……好像沒有變化嘛。

聰明的你,一定可以舉一反三,發(fā)現還是由于“關系”(links$relation)屬性不是“因子”導致的。

我們把 relation 屬性轉換成因子類型。

links$relation <- as.factor(links$relation)
links$color <- c("green", "red")[links$relation]
visNetwork(nodes, links)

太棒了!

下面,我們還是以年級作為交互選項,加入進來。

links$relation <- as.factor(links$relation)
links$color <- c("green", "red")[links$relation]
visNetwork(nodes, links) %>%
  visOptions(selectedBy = "grade")

我們選擇一下年級,拖動節(jié)點看看:

以上,是樣例代碼中,出現的內容解釋。

小結

通過本文的學習,相信你已經掌握如何把社會網絡的表格數據,用交互可視化的方法展現出來。

對于不同的元素,你也已經學會了基本的展現方式。

但請你一定不要止步于此。

首先,你需要繼續(xù)查看文檔。里面還有很多選項參數,此處我們沒有涉及。例如說,這里我們只繪制了“關系”(邊),但是卻沒有在其上進行任何文字標記。

如果你需要生成非常嚴肅的數據可視化作品,這些內容很可能用得上。請你點擊這個鏈接,查看完整的文檔。從中選擇自己感興趣的部分深入研讀。

另外,這個工具,也絕不僅僅可以幫助你繪制社會網絡圖。只要是適合用網絡圖展現的內容,它都可以發(fā)揮作用。

希望你充分發(fā)揮自己舉一反三的能力,把這項新技能用好。

祝學習愉快!

延伸閱讀

你可能也會對以下話題感興趣。點擊鏈接就可以查看。

喜歡請點贊和打賞。還可以微信關注和置頂我的公眾號“玉樹芝蘭”(nkwangshuyi)。

如果你對 Python 與數據科學感興趣,不妨閱讀我的系列教程索引貼《如何高效入門數據科學?》,里面還有更多的有趣問題及解法。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容