手把手:一張圖看清編程語言發展史,你也能用Python畫出來!

今天文摘菌要教你們製做一張編程語言的關係網絡圖。若是不知道什麼是關係網絡圖,能夠點擊下方連接先來看一下最終成果:html

http://programming-languages.herokuapp.com/#,node

咱們能夠在這裏看到從過去到如今的250多種編程語言之間的「設計影響」的關係,下面是該演示的截圖:python

9bed6a06817dfca6c0606ef708709759013da578

接下來,就讓咱們一塊兒來學作這個關係網絡圖吧!git

在當今的超鏈接世界,網絡在現代生活中無處不在。舉個栗子,文摘菌的週末這樣開啓——經過北京的交通網絡進城,而後去最喜歡的咖啡店的一家分店,並將筆記本連上他們的Wi-Fi。接下來,登陸各類經常使用的社交網站。github

衆所周知,在過去幾十年來最有影響力的公司中,有一部分是由於網絡的力量而得到成功。正則表達式

Facebook、Twitter、Instagram、LinkedIn以及一些其餘的社交媒體平臺都依賴社交網絡的小世界特性。這使他們能有效地將用戶彼此(以及和廣告商)之間鏈接起來。算法

谷歌目前的成功主要歸因於他們早期在搜索引擎市場上的主導地位——部分緣由是他們有能力經過他們的Page Rank網絡算法來返回相關的結果。編程

亞馬遜的高效配送網絡使他們可以在一些主要城市提供當天發貨。ubuntu

網絡算法在人工智能和機器學習等領域也是很是重要的。神經網絡領域的研究很是熱門。計算機視覺中許多必不可少的特徵檢測算法,在很大程度上也是依賴於使用網絡來對圖像的不一樣部分進行建模。瀏覽器

網絡模型也能夠解釋大量的科學現象,包括有量子力學、生化途徑以及生態和社會經濟系統等。

那麼,鑑於它們不能否認的重要性,咱們應該如何更好地理解網絡及其屬性呢?

網絡的數學研究被稱爲「圖論」,是數學中較易理解的分支之一。 本文會介紹簡單的網絡知識,即使你沒有相關背景知識也能輕鬆學會。

此外,咱們將使用Python 3.x和一款很是棒的開源軟件Gephi,經過關係網絡將過去和如今的一系列編程語言的網絡可視化聯繫起來。

首先,究竟什麼是網絡呢?

其實上面文摘菌舉的栗子已經給了一些線索。交通網絡由目的和路徑的鏈接組成。社交網絡經過我的和我的之間的關係進行鏈接。Google的搜索引擎算法經過查看有哪些頁面連接到其餘頁面,來評估不一樣網頁的「順序」。

更通常地說,網絡是能夠用節點和邊描述的任何系統,或者通俗來說,就是咱們所說的「點和線」。

f403f1b99d50931ff358c5e657da6fa3edcbc05f

邊鏈接節點(語言)的例子(該網絡表示了編程語言相互影響的關係)

有些系統以這種方式創建網絡比較容易。社交網絡也許是最明顯的例子。計算機文件系統則是另外一種方式——文件夾和文件經過其「父」和「子」關係建立鏈接。

可是,網絡的真正威力其實在於,許多系統均可以從網絡的角度來建模,即便這起初並不明顯。

表明網絡

咱們應該如何將點和線的圖片轉換成咱們能夠壓縮的數字信號呢?

其中有一個解決方案是繪製一個鄰接矩陣來表示咱們的網絡。

若是你不熟悉矩陣這個概念,這聽起來可能有點嚇人,但不要懼怕。 把它們想象成能夠一次執行許多計算的數字網格就好。下面是一個簡單的例子:

dc59e4861c4a3da63df5bac8677dac05b901a4c1

在這個矩陣中,每一個行和列的交集都是0或1,這取決於各個語言是否被連接。你也能夠根據上面的插圖觀察到!

對於要解決的大多數問題而言,矩陣是以數學方式表示網絡的好方法。然而從計算的角度來看,它有時可能會有點麻煩。

例如,即便節點數量相對較少(好比說有1000個),矩陣中的元素數目也會大得多(例如,1000^2 = 1,000,000)。

許多現實世界的系統會產生稀疏網絡,在這些網絡中,大多數節點只能鏈接其餘全部節點中的一小部分。

若是咱們將計算機內存中1000個節點的稀疏網絡表示爲鄰接矩陣,那麼咱們將在RAM中存儲1,000,000個字節的數據。大多數將會是零。這裏有一個更爲有效的方法能夠解決這個問題。

這種方法是使用邊列表來代替鄰接矩陣。這些正是他們所說的,它們只是一個節點對相互連接的列表。

表示網絡的另外一種手段是鄰接表,它列出了每一個節點後面與它進行連接的節點。例如:

54c037551f1c6644cb22f5f54fd5cc943e60db06

收集數據,創建鏈接

任何網絡模型以及可視化的表現都取決於構建網絡自己所用的數據質量好壞。除了確保數據是準確和完整的同時,咱們也須要一種推斷節點之間邊的合理方法。

這是至關關鍵的一步,隨後對網絡進行的任何分析和推斷都取決於「關聯標準」的合理性。

例如,在社交網絡分析中,你可能會根據人們是否在社交媒體上相互關聯來建立人與人之間的聯繫。在分子生物學中,你可能會基於基因的共同表達創建鏈接。

一般,咱們還能夠給邊分配權重,從而體現關係的「強度」。

例如,對於網上零售的狀況,能夠根據產品被同時購買的頻率來計算權重。用高權重的邊鏈接常常被同時購買的產品,用低權重的邊鏈接偶爾被同時購買的產品。和偶爾被同時購買的產品相比,那些不會被同時購買的產品根本就不會被網絡鏈接。

正如你想的那樣,將節點彼此鏈接的方法有可能很複雜。

可是對於本教程,咱們將使用更簡單的方式鏈接編程語言。咱們要依靠維基百科。

維基百科所取得的的成功證實了它的可靠性。文章寫做的開源合做方法也應該保證必定程度的客觀性。

並且,它的頁面結構相對一致,使其成爲試用網頁抓取技術的便利場所。

另外一個便利工具是覆蓋面普遍的、有據可查的維基百科API,這使得信息檢索更容易。接下來讓咱們一塊兒開始吧。

第一步:安裝Gephi

Gephi可在Linux、Mac和Windows的環境下進行安裝。

對於這個項目,我使用了Lubuntu。若是你使用的是Ubuntu / Debian,那麼你能夠按照下面的步驟來啓動和運行Gephi。若是不是,那麼安裝過程也不會差太多。

下載最新版本的Gephi到你的系統(在撰寫本文時是v.0.9.1)。準備就緒後,你須要提取文件。

b7d44a704c0a7c81cea92ab5cd2a6f9808f82358

你可能須要檢查你的Java JRE版本。Gephi須要最新版本。在我剛剛安裝的Lubuntu上,我只安裝了default-jre,下面的一切將創建在此基礎上。

fd77240077977255a3fdaeb216254aca208709d6

在你準備好進行安裝以前還有一步。爲了將圖表導出到Web,你可使用Gephi的Sigma.js插件。

從Gephi的菜單欄中選擇「工具」選項,而後選擇「插件」。

點擊「可用插件」標籤並選擇「SigmaExporter」(我也安裝了JSON導出器,由於它是另外一個有用的插件)。

點擊「安裝」按鈕,你將完成整個安裝過程。安裝結束後,你須要從新啓動Gephi。

第二步:編寫Python腳本

本教程將使用python 3.x以及一些模塊來進行簡化。使用pip模塊安裝程序,需運行一下命令:

9f9891a1e47a0a672dbf0a70fdd4bd2e91ad0747

如今,在一個新的目錄中,建立一個名爲script.py的文件,並在你最喜歡的代碼編輯器/ IDE中打開它。如下是主要邏輯的大綱:

首先,你須要有一個編程語言的列表。

接下來,經過該列表並檢索維基百科相關文章的HTML。

從中提取出每種語言所影響的編程語言列表。這是咱們鏈接節點的粗略標準。

同時,咱們能夠抓取一些關於每種語言的元數據。

最後,將收集的全部數據寫入一個.csv文件。

完整的腳本在這裏:

(https://gist.github.com/anonymous/2a6c841fe04ebc6d55acc259b4ac4f72)。

導入模塊

在script.py中,首先導入一些模塊。

bdbba015866c2d94dcbc9f367dbe2f33bdf875d1

準備好後——從建立一個節點的列表開始。這是Wikipedia模塊派上用場的地方。它使得訪問維基百科API很是容易。

添加下面的代碼:

40105750d7c48b3b0e885e24925796f3c71d8785

保存並運行上面的腳本,將看到打印出「List of programming languages」維基百科文章中的全部連接。

另外,還須要手動檢查自動收集的數據。快速瀏覽後咱們能夠發現,除了許多實際的編程語言以外,該腳本還提供了一些額外的連接。

如:可能會看到「List of markup languages」,「Comparison of programming languages」等。

雖然Gephi容許你移除不想包含的節點,但爲了節省時間,仍是讓咱們先進行一輪數據清洗。

b60dce5136478696a3be6777b0d5a8297a18bef7

這些代碼定義了要從數據中移除的子字符串列表。運行該腳本時遍歷數據,移除全部包含不須要的子字符串的元素。

在Python語言中,完成這些只須要一行代碼!

其餘輔助函數

如今咱們能夠開始從wikipedia抓取數據並創建一個邊列表(並收集全部元數據)。爲了更簡便,讓咱們首先定義一些函數。

抓取HTML

第一個函數使用BeautifulSoup模塊來獲取每種語言的Wikipedia頁面的HTML。

9ee58826a3cf99dde5338cd3e7c5485c9b47700c

這個函數使用urllib.request模塊來獲取「https://en.wikipedia.org/wiki/」+「編程語言」頁面的HTML。

而後傳給BeautifulSoup,它將讀取HTML並解析爲一個能夠用來搜索信息的對象。

接下來,使用find_all()方法抓取感興趣的HTML元素。

下面,是每種編程語言文章頂部的彙總表。該如何識別呢?

最簡單的方法是訪問其中一個編程語言頁面。在這裏,能夠簡單地使用瀏覽器的開發工具來檢查感興趣的元素。彙總表有HTML標記<table>和CSS類「infobox」和「vevent」,所以可使用這些來標識HTML中的表格。

用參數指定它:

cff7d906beb9a906a90b27d1684c11b842465089

find_all()返回符合標準的全部元素列表。爲了指定感興趣的元素,須要添加索引[0]。若是函數執行成功,則返回table對象,不然,返回None。

a9ca08f3dcbe88810d66c7380c51ce45e4d3f671

在使用了自動數據收集程序的狀況下,全面的異常處理是很是重要的。若是沒有,那麼在最好的狀況下若是腳本崩潰了,數據抓取程序須要從新開始執行。

在最壞的狀況下,你得到數據集將包含不一致性和錯誤,這將爲你後續的工做買下隱患。

檢索元數據

下一個函數使用table對象來查找一些元數據。下面給出在表格中搜索語言第一次出現的年份的代碼。

f16a17c6bcd407c17bc3e62fb56ba157dfd59175

這個簡短的函數以table對象做爲參數,並調用BeautifulSoup的get_text()函數生成一個字符串。

下一步是建立一個名爲year的子字符串。該字符串存儲了在「appear」這個詞首次出現以後的30個字符。這個字符串應該包含語言第一次出現的年份。

爲了僅提取年份,使用正則表達式(經過re模塊)來匹配任何以1到3之間的數字開頭、並緊鄰三個數字的字符串。

24af68410d8a75dbf222e88b14a5a0e64f15313d

若是執行成功,函數將返回一個整數的year。不然,咱們會獲得「Could not determine」。你可能還想進一步挖掘元數據,例如範例,設計者或打字規律。

收集連接

咱們還須要一個函數–該函數讀入給定語言的table對象,輸出一個包含其餘編程語言的列表。

cb3c79c3582df9dbd5e67b25b7e7584d4f1d2eac

仔細觀察上面代碼中嵌套部分,究竟是怎麼回事呢?

這個函數利用了table對象具備結構一致性的事實。表中的信息存儲在行中(相關的HTML標籤是<tr>)。其中一行包含文字「\ nInfluenced \ n」。函數的第一部分查找這是哪一行。

一旦找到這一行,就能夠肯定下一行包含了被當前行影響的每種編程語言的連接。使用find_all(「a」)即可查找這些連接 - 其中參數「a」對應於HTML標籤<a>。

對於每一個連接j,將其[「title」]屬性添加到名爲out的列表。對[「title」]屬性感興趣的緣由是由於它將徹底匹配存儲在節點中的語言名稱。

例如,Java做爲「Java(編程語言)」存儲在節點中,所以須要在整個數據集中使用這個確切的名稱。

若是執行成功,getLinks()將返回一組編程語言。該函數的其他部分進行了異常處理,以防程序在某一階段出現問題。

收集數據

最後,在一切準備就緒後執行腳本,收集數據並將其存儲在兩個列表對象中。

91dd614271c14183e78c5c260d7da22fb581d357

如今編寫一個循環,將先前定義的函數應用於nodes中的每一個詞條,並將輸出存儲在edgeList和meta中。

94ccfadfe6cab21a7c04e01f5a1a3571317985f5

該函數使用節點中的每種語言,並嘗試從維基百科頁面檢索彙總表。

而後,該函數將檢索表中列出的與目標語言所關聯的所有語言。

對於同時出如今節點列表中的每種語言,將一個元素以[「source,target」]的形式添加到edgeList。經過這種方式,創建一個邊的列表傳給Gephi。

出於調試的目的,打印添加到edgeList的每一個元素——這樣作僅僅爲了確保一切都工做。若是想要更完全地調試,也能夠添加打印語句到except語句中。

接下來,獲取語言的名稱和年份,並將其添加到元列表中。

寫進CSV文件

一旦循環運行,最後一步是將edgeList和meta的內容寫入到CSV文件。經過使用前面導入的csv模塊,完成上一步驟就容易多了。

004c22c78c5689fad9a54f75e6c300531b439547

完成了!保存腳本,並從終端運行:

$ python3 script.py

當構建邊列表時,你能夠看到腳本輸出了source-target對。確保網絡鏈接的穩定性後,你就能夠坐等結果了,此時腳本將發揮其魔力。

第三步:用Gephi創建圖形

但願你已經安裝並運行了Gephi。如今你能夠建立一個新項目,並使用你收集的數據來構建有向圖。有向圖將顯示不一樣的編程語言是如何相互影響的!

首先在Gephi中建立一個新項目,而後切換到「數據實驗室」窗口。Gephi中提供了一個擴展式的接口來處理數據。首先要導入列表。

點擊「導入電子表格」。

選擇由Python腳本生成的edge_list.csv文件。確保Gephi中使用逗號做爲分隔符。

從列表類型中選擇「邊列表」

點擊「下一步」,導入源和目標列做爲字符串,並檢查。

用一個節點列表來更新數據實驗室。如今,導入 metadata.csv文件。這一次,從列表類型中選擇「節點列表」。

切換到「Preview」選項卡,查看網絡的外觀。

這時的圖形看起來顏色十分單一,並且雜亂無章,就像一盤意大利麪。因此咱們接下來要進行圖像美化。

圖像美化

咱們能夠經過各類方式來演示圖像,也能夠盡情發揮本身的創意。另外,關於網絡可視化還要考慮如下三件事情:

節點定位:生成網絡佈局模式的算法有不少,比較流行的是fruchterman - reingold算法,並且Gephi支持該算法。

節點大小:圖中節點的大小能夠用來表示一些有趣的屬性。一般,這是一箇中心性度量。度量中心性的方法有不少,但它們都反映了給定節點的「重要性」,即它與網絡的其餘部分關聯的緊密程度。

節點着色:咱們還可使用顏色來顯示節點的某些屬性。一般,顏色用來表示羣落結構,普遍定義爲「與圖的其他部分相比關聯更緊密的一組節點」。在社交網絡中,羣落結構能夠揭示我的的友情、家庭或專業團體之間的關聯。有幾種算法能夠檢測羣落結構,Gephi自帶的檢測算法是Louvain方法。

要執行上述步驟,還須要計算一些統計數據。切換到「Overview」窗口。在這裏你能夠看到右側的一個面板。它包含一個「Statistics」選項卡。打開它,你將看到一系列選項。

Gephi具備許多內置的統計功能。對於每種功能,點擊「Run」將生成一個報告,該報告揭示了關於網絡的一些洞見。

若是要修改網絡的外觀,咱們能夠轉向左邊的面板。

在「Layout」選項卡中,能夠選擇要使用的佈局算法。點擊「運行」,實時觀看圖表的變化!看看你認爲哪一種佈局算法效果最好。

在Layout選項卡之上是「Appearance」選項卡。在這裏,你能夠爲節點和各條邊的顏色、大小和標籤進行設置,也能夠根據數據的屬性來配置(包括你要計算的數據)。

一個建議:

根據模塊化屬性將節點着色。着色的根據是節點的羣落成員關係。

根據節點的平均程度來肯定節點的大小。關聯緊密的節點會比關聯稀疏的節點顯得大。

不過,也能夠嘗試設計一個最喜歡的佈局。一旦對圖形外觀感到滿意,就能夠進入最後一個步驟——將圖形導出至網頁!

第四步:使用Sigma.js插件

既然已經構建了一個能夠在Gephi中查看的網絡可視化,接下來能夠選擇使用屏幕截圖,或者以SVG、PDF或PNG格式保存圖形。

若是已經安裝了Sigma.js插件,也能夠把圖形導出到HTML,這將會建立一個交互式可視化,不只能夠在線上發佈,也能夠上傳到GitHub,與他人分享。

可從Gephi的菜單欄選擇「Export >Sigma.js模板…」。

按要求填寫詳細信息。確保選擇導出項目所在的目錄。你也能夠更改圖形的標題、圖例、描述、懸停和許多其餘細節。當你準備好了,點擊「肯定」。

如今,若是你打開導出項目所在的目錄,你將看到一個文件夾,其中包含Sigma.js生成的全部文件。

在你最喜歡的瀏覽器打開index.html文件。哈!你的網絡!若是你知道一些CSS和JavaScript,能夠載入各類生成的文件到你的網絡中,以便按照你的意願調整輸出的網絡。

腦洞開一開,網絡畫起來

許多系統能夠做爲網絡進行建模和可視化。圖論是數學的一個分支,它提供了幫助理解網絡結構和屬性的工具。

使用Python從Wikipedia獲取數據,構建編程語言影響圖。關聯標準是一種給定的語言是否能被列爲對設計另外一種語言的影響。

Gephi和Sigma.js是分析和可視化網絡的開源工具。它們可讓你以圖像、PDF或Web格式導出網絡。

模仿本文的方法,你還能夠爲不少其餘的關係建模並作出可視化。腦洞開一開,網絡畫起來。

閱讀原文http://click.aliyun.com/m/40110/

相關文章
相關標籤/搜索