手把手:一張圖看清編程語言發展史,你也能用Python畫出來!
大數據文摘作品
作者:Peter Gleeson
編譯:周佳玉、丁慧、葉一、小魚、錢天培
今天文摘菌要教大家製作一張編程語言的關係網路圖。如果不知道什麼是關係網路圖,可以點擊下方鏈接先來看一下最終成果:
http://programming-languages.herokuapp.com/#,
我們可以在這裡看到從過去到現在的250多種編程語言之間的「設計影響」的關係,下面是該演示的截圖:
接下來,就讓我們一起來學做這個關係網路圖吧!
在當今的超連接世界,網路在現代生活中無處不在。舉個栗子,文摘菌的周末這樣開啟——通過北京的交通網路進城,然後去最喜歡的咖啡店的一家分店,並將筆記本連上他們的Wi-Fi。接下來,登錄各種常用的社交網站。
眾所周知,在過去幾十年來最有影響力的公司中,有一部分是因為網路的力量而獲得成功。
Facebook、Twitter、Instagram、LinkedIn以及一些其他的社交媒體平台都依賴社交網路的小世界特性。這使他們能有效地將用戶彼此(以及和廣告商)之間連接起來。
谷歌目前的成功主要歸因於他們早期在搜索引擎市場上的主導地位——部分原因是他們有能力通過他們的Page Rank網路演算法來返回相關的結果。
亞馬遜的高效配送網路使他們能夠在一些主要城市提供當天發貨。
網路演算法在人工智慧和機器學習等領域也是非常重要的。神經網路領域的研究非常熱門。計算機視覺中許多必不可少的特徵檢測演算法,在很大程度上也是依賴於使用網路來對圖像的不同部分進行建模。
網路模型也可以解釋大量的科學現象,包括有量子力學、生化途徑以及生態和社會經濟系統等。
那麼,鑒於它們不可否認的重要性,我們應該如何更好地理解網路及其屬性呢?
網路的數學研究被稱為「圖論」,是數學中較易理解的分支之一。本文會介紹簡單的網路知識,即便你沒有相關背景知識也能輕鬆學會。
此外,我們將使用Python 3.x和一款非常棒的開源軟體Gephi,通過關係網路將過去和現在的一系列編程語言的網路可視化聯繫起來。
首先,究竟什麼是網路呢?
其實上面文摘菌舉的栗子已經給了一些線索。交通網路由目的和路徑的連接組成。社交網路通過個人和個人之間的關係進行連接。Google的搜索引擎演算法通過查看有哪些頁面鏈接到其他頁面,來評估不同網頁的「順序」。
更一般地說,網路是可以用節點和邊描述的任何系統,或者通俗來講,就是我們所說的「點和線」。
邊連接節點(語言)的例子(該網路表示了編程語言相互影響的關係)
有些系統以這種方式建立網路比較容易。社交網路也許是最明顯的例子。計算機文件系統則是另一種方式——文件夾和文件通過其「父」和「子」關係創建連接。
但是,網路的真正威力其實在於,許多系統都可以從網路的角度來建模,即使這起初並不明顯。
代表網路
我們應該如何將點和線的圖片轉換成我們可以壓縮的數字信號呢?
其中有一個解決方案是繪製一個鄰接矩陣來表示我們的網路。
如果你不熟悉矩陣這個概念,這聽起來可能有點嚇人,但不要害怕。 把它們想像成可以一次執行許多計算的數字網格就好。下面是一個簡單的例子:
在這個矩陣中,每個行和列的交集都是0或1,這取決於各個語言是否被鏈接。你也可以根據上面的插圖觀察到!
對於要解決的大多數問題而言,矩陣是以數學方式表示網路的好方法。然而從計算的角度來看,它有時可能會有點麻煩。
例如,即使節點數量相對較少(比如說有1000個),矩陣中的元素數目也會大得多(例如,1000^2 = 1,000,000)。
許多現實世界的系統會產生稀疏網路,在這些網路中,大多數節點只能連接其他所有節點中的一小部分。
如果我們將計算機內存中1000個節點的稀疏網路表示為鄰接矩陣,那麼我們將在RAM中存儲1,000,000個位元組的數據。大多數將會是零。這裡有一個更為有效的方法可以解決這個問題。
這種方法是使用邊列表來代替鄰接矩陣。這些正是他們所說的,它們只是一個節點對相互鏈接的列表。
表示網路的另一種手段是鄰接表,它列出了每個節點後面與它進行鏈接的節點。例如:
收集數據,建立連接
任何網路模型以及可視化的表現都取決於構建網路本身所用的數據質量好壞。除了確保數據是準確和完整的同時,我們也需要一種推斷節點之間邊的合理方法。
這是相當關鍵的一步,隨後對網路進行的任何分析和推斷都取決於「關聯標準」的合理性。
例如,在社交網路分析中,你可能會根據人們是否在社交媒體上相互關聯來創建人與人之間的聯繫。在分子生物學中,你可能會基於基因的共同表達建立連接。
通常,我們還可以給邊分配權重,從而體現關係的「強度」。
例如,對於網上零售的情況,可以根據產品被同時購買的頻率來計算權重。用高權重的邊連接經常被同時購買的產品,用低權重的邊連接偶爾被同時購買的產品。和偶爾被同時購買的產品相比,那些不會被同時購買的產品根本就不會被網路連接。
正如你想的那樣,將節點彼此連接的方法有可能很複雜。
但是對於本教程,我們將使用更簡單的方式連接編程語言。我們要依靠維基百科。
維基百科所取得的的成功證明了它的可靠性。文章寫作的開源合作方法也應該保證一定程度的客觀性。
而且,它的頁面結構相對一致,使其成為試用網頁抓取技術的便利場所。
另一個便利工具是覆蓋面廣泛的、有據可查的維基百科API,這使得信息檢索更容易。接下來讓我們一起開始吧。
第一步:安裝Gephi
Gephi可在Linux、Mac和Windows的環境下進行安裝。
對於這個項目,我使用了Lubuntu。如果你使用的是Ubuntu / Debian,那麼你可以按照下面的步驟來啟動和運行Gephi。如果不是,那麼安裝過程也不會差太多。
下載最新版本的Gephi到你的系統(在撰寫本文時是v.0.9.1)。準備就緒後,你需要提取文件。
你可能需要檢查你的Java JRE版本。Gephi需要最新版本。在我剛剛安裝的Lubuntu上,我只安裝了default-jre,下面的一切將建立在此基礎上。
在你準備好進行安裝之前還有一步。為了將圖表導出到Web,你可以使用Gephi的Sigma.js插件。
從Gephi的菜單欄中選擇「工具」選項,然後選擇「插件」。
點擊「可用插件」標籤並選擇「SigmaExporter」(我也安裝了JSON導出器,因為它是另一個有用的插件)。
點擊「安裝」按鈕,你將完成整個安裝過程。安裝結束後,你需要重新啟動Gephi。
第二步:編寫Python腳本
本教程將使用python 3.x以及一些模塊來進行簡化。使用pip模塊安裝程序,需運行一下命令:
現在,在一個新的目錄中,創建一個名為script.py的文件,並在你最喜歡的代碼編輯器/ IDE中打開它。以下是主要邏輯的大綱:
首先,你需要有一個編程語言的列表。
接下來,通過該列表並檢索維基百科相關文章的HTML。
從中提取出每種語言所影響的編程語言列表。這是我們連接節點的粗略標準。
同時,我們可以抓取一些關於每種語言的元數據。
最後,將收集的所有數據寫入一個.csv文件。
完整的腳本在這裡:
(https://gist.github.com/anonymous/2a6c841fe04ebc6d55acc259b4ac4f72)。
導入模塊
在script.py中,首先導入一些模塊。
準備好後——從創建一個節點的列表開始。這是Wikipedia模塊派上用場的地方。它使得訪問維基百科API非常容易。
添加下面的代碼:
保存並運行上面的腳本,將看到列印出「List of programming languages」維基百科文章中的所有鏈接。
另外,還需要手動檢查自動收集的數據。快速瀏覽後我們可以發現,除了許多實際的編程語言之外,該腳本還提供了一些額外的鏈接。
如:可能會看到「List of markup languages」,「Comparison of programming languages」等。
雖然Gephi允許你移除不想包含的節點,但為了節省時間,還是讓我們先進行一輪數據清洗。
這些代碼定義了要從數據中移除的子字元串列表。運行該腳本時遍曆數據,移除所有包含不需要的子字元串的元素。
在Python語言中,完成這些只需要一行代碼!
其他輔助函數
現在我們可以開始從wikipedia抓取數據並建立一個邊列表(並收集所有元數據)。為了更簡便,讓我們首先定義一些函數。
抓取HTML
第一個函數使用BeautifulSoup模塊來獲取每種語言的Wikipedia頁面的HTML。
這個函數使用urllib.request模塊來獲取「https://en.wikipedia.org/wiki/」+「編程語言」頁面的HTML。
然後傳給BeautifulSoup,它將讀取HTML並解析為一個可以用來搜索信息的對象。
接下來,使用find_all()方法抓取感興趣的HTML元素。
下面,是每種編程語言文章頂部的匯總表。該如何識別呢?
最簡單的方法是訪問其中一個編程語言頁面。在這裡,可以簡單地使用瀏覽器的開發工具來檢查感興趣的元素。匯總表有HTML標記和CSS類「infobox」和「vevent」,因此可以使用這些來標識HTML中的表格。
用參數指定它:
find_all()返回符合標準的所有元素列表。為了指定感興趣的元素,需要添加索引[0]。如果函數執行成功,則返回table對象,否則,返回None。
在使用了自動數據收集程序的情況下,全面的異常處理是非常重要的。如果沒有,那麼在最好的情況下如果腳本崩潰了,數據抓取程序需要重新開始執行。
在最壞的情況下,你獲得數據集將包含不一致性和錯誤,這將為你後續的工作買下隱患。
檢索元數據
下一個函數使用table對象來查找一些元數據。下面給出在表格中搜索語言第一次出現的年份的代碼。
這個簡短的函數以table對象作為參數,並調用BeautifulSoup的get_text()函數生成一個字元串。
下一步是創建一個名為year的子字元串。該字元串存儲了在「appear」這個詞首次出現之後的30個字元。這個字元串應該包含語言第一次出現的年份。
為了僅提取年份,使用正則表達式(通過re模塊)來匹配任何以1到3之間的數字開頭、並緊鄰三個數字的字元串。
如果執行成功,函數將返回一個整數的year。否則,我們會得到「Could not determine」。你可能還想進一步挖掘元數據,例如範例,設計者或打字規律。
收集鏈接
我們還需要一個函數–該函數讀入給定語言的table對象,輸出一個包含其他編程語言的列表。
仔細觀察上面代碼中嵌套部分,到底是怎麼回事呢?
這個函數利用了table對象具有結構一致性的事實。表中的信息存儲在行中(相關的HTML標籤是)。其中一行包含文字「 nInfluenced n」。函數的第一部分查找這是哪一行。
一旦找到這一行,就可以確定下一行包含了被當前行影響的每種編程語言的鏈接。使用find_all(「a」)便可查找這些鏈接 - 其中參數「a」對應於HTML標籤。
對於每個鏈接j,將其[「title」]屬性添加到名為out的列表。對[「title」]屬性感興趣的原因是因為它將完全匹配存儲在節點中的語言名稱。
例如,Java作為「Java(編程語言)」存儲在節點中,因此需要在整個數據集中使用這個確切的名稱。
如果執行成功,getLinks()將返回一組編程語言。該函數的其餘部分進行了異常處理,以防程序在某一階段出現問題。
收集數據
最後,在一切準備就緒後執行腳本,收集數據並將其存儲在兩個列表對象中。
現在編寫一個循環,將先前定義的函數應用於nodes中的每個詞條,並將輸出存儲在edgeList和meta中。
該函數使用節點中的每種語言,並嘗試從維基百科頁面檢索匯總表。
然後,該函數將檢索表中列出的與目標語言所關聯的全部語言。
對於同時出現在節點列表中的每種語言,將一個元素以[「source,target」]的形式添加到edgeList。通過這種方式,建立一個邊的列表傳給Gephi。
出於調試的目的,列印添加到edgeList的每個元素——這樣做僅僅為了確保一切都工作。如果想要更徹底地調試,也可以添加列印語句到except語句中。
接下來,獲取語言的名稱和年份,並將其添加到元列表中。
寫進CSV文件
一旦循環運行,最後一步是將edgeList和meta的內容寫入到CSV文件。通過使用前面導入的csv模塊,完成上一步驟就容易多了。
完成了!保存腳本,並從終端運行:
$ 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格式導出網路。
模仿本文的方法,你還可以為很多其他的關係建模並做出可視化。腦洞開一開,網路畫起來。
https://medium.freecodecamp.org/how-to-visualize-the-programming-language-influence-graph-7f1b765b44d1
機器學習和人工智慧崗位
求職福利
看書看視頻?刷題?蹭項目經歷?海投?
帶你解鎖機器學習高效求職新方式
AI時代,時間和機會是極具回報價值的投資!
※Python編程培訓中你遇到捷da徑keng了嗎?來千鋒讓你不中招!
TAG:Python |