七個用于數(shù)據(jù)科學(data science)的命令行工具
數(shù)據(jù)科學是OSEMN(和 awesome 相同發(fā)音),它包括獲取(Obtaining)、整理(Scrubbing)、探索(Exploring)、建模(Modeling)和翻譯(iNterpreting)數(shù)據(jù)。作為一名數(shù)據(jù)科學家,我用命令行的時間非常長,尤其是要獲取、整理和探索數(shù)據(jù)的時候。而且我也不是唯一一個這樣做的人。最近,Greg Reda介紹了可用于數(shù)據(jù)科學的經(jīng)典命令行工具。在這之前,Seth Brown介紹了如何在Unix下進行探索性的數(shù)據(jù)分析。
下面我將介紹在我的日常工作中發(fā)現(xiàn)很有用的七個命令行工具。包括:jq、 json2csv、 csvkit、scrape、 xml2json、 sample 和 Rio。(我自己做的scrape、sample和Rio可以在這里拿到)。任何建議意見、問題甚至git上的拉取請求都非常歡迎(其他人建議的工具可以在***找到)。好的,下面我們首先介紹jq。
1. jq – sed for JSON
JSON現(xiàn)在越來越流行,尤其當API盛行了以后。我還記得處理JSON時,用grep和sed寫著丑陋的代碼。謝謝jq,終于可以不用寫的這么丑了。
假設(shè)我們對2008總統(tǒng)大選的所有候選人感興趣。紐約時報有一個關(guān)于競選財務的API。讓我們用curl取一些JSON:
- curl -s 'http://api.nytimes.com/svc/elections/us/v3/finances/2008/president/totals.json?api-key=super-secret' > nyt.json
-s表示靜默模式。然后我們用jq最簡單的格式j(luò)q ‘.’,可以把得到的丑陋的代碼:
- {"status":"OK","base_uri":"http://api.nytimes.com/svc/elections/us/v3/finances/2008/","cycle":2008,"copyright":"Copyright (c) 2013 The New York Times Company. All Rights Reserved.","results":[{"candidate_name":"Obama, Barack","name":"Barack Obama","party":"D",
轉(zhuǎn)換成漂亮的格式:
- < nyt.json jq '.' | head { "results": [ { "candidate_id": "P80003338", "date_coverage_from": "2007-01-01", "date_coverage_to": "2008-11-24", "candidate_name": "Obama, Barack", "name": "Barack Obama", "party": "D",
同時,jq還可以選取和過濾JSON數(shù)據(jù):
- < nyt.json jq -c '.results[] | {name, party, cash: .cash_on_hand} | select(.cash | tonumber > 1000000)'
- {"cash":"29911984.0","party":"D","name":"Barack Obama"}
- {"cash":"32812513.75","party":"R","name":"John McCain"}
- {"cash":"4428347.5","party":"D","name":"John Edwards"}
更多使用方法參見手冊,但是不要指望jq能做所有事。Unix的哲學是寫能做一件事并且做得好的程序,但是jq功能強大!下面就來介紹json2csv。
2. json2csv – 把JSON轉(zhuǎn)換成CSV
雖然JSON適合交換數(shù)據(jù),但是它不適合很多命令行工具。但是不用擔心,用json2csv我們可以輕松把JSON轉(zhuǎn)換成CSV。現(xiàn)在假設(shè)我們把數(shù)據(jù)存在million.json里,僅僅調(diào)用
- < million.json json2csv -k name,party,cash
就可以把數(shù)據(jù)轉(zhuǎn)換成:
- Barack Obama,D,29911984.0
- John McCain,R,32812513.75
- John Edwards,D,4428347.5
有了CSV格式我們就可以用傳統(tǒng)的如 cut -d 和 awk -F 一類的工具了。grep和sed沒有這樣的功能。因為CSV是以表格形式存儲的,所以csvkit的作者開發(fā)了csvkit。
3. csvkit – 轉(zhuǎn)換和使用CSV的套裝
csvkit不只是一個程序,而是一套程序。因為大多數(shù)這類工具“期望”CSV數(shù)據(jù)有一個表頭,所以我們在這里加一個。
- echo name,party,cash | cat - million.csv > million-header.csv
我們可以用csvsort給候選人按競選資金排序并展示:
- < million-header.csv csvsort -rc cash | csvlook
- |---------------+-------+--------------|
- | name | party | cash |
- |---------------+-------+--------------|
- | John McCain | R | 32812513.75 |
- | Barack Obama | D | 29911984.0 |
- | John Edwards | D | 4428347.5 |
- |---------------+-------+--------------|
看起來好像MySQL哈?說到數(shù)據(jù)庫,我們可以把CSV寫到sqlite數(shù)據(jù)庫(很多其他的數(shù)據(jù)庫也支持)里,用下列命令:
- csvsql --db sqlite:///myfirst.db --insert million-header.csv
- sqlite3 myfirst.db
- sqlite> .schema million-header
- CREATE TABLE "million-header" (
- name VARCHAR(12) NOT NULL,
- party VARCHAR(1) NOT NULL,
- cash FLOAT NOT NULL
- );
插入后數(shù)據(jù)都會正確因為CSV里也有格式。此外,這個套裝里還有其他有趣工具,如 in2csv、 csvgrep 和csvjoin。通過csvjson,數(shù)據(jù)甚至可以從csv轉(zhuǎn)換會json??傊阒档靡豢?。
4. scrape – 用XPath和CSS選擇器進行HTML信息提取的工具
JSON雖然很好,但是同時也有很多資源依然需要從HTML中獲取。scrape就是一個Python腳本,包含了lxml和cssselect包,從而能選取特定HTML元素。維基百科上有個網(wǎng)頁列出了所有國家的邊界線語國土面積的比率,下面我們來把比率信息提取出來吧。
- curl -s 'http://en.wikipedia.org/wiki/List_of_countries_and_territories_by_border/area_ratio' | scrape -b -e 'table.wikitable > tr:not(:first-child)' | head
- <!DOCTYPE html>
- <html>
- <body>
- <tr>
- <td>1</td>
- <td>Vatican City</td>
- <td>3.2</td>
- <td>0.44</td>
- <td>7.2727273</td>
- </tr>
-b命令讓scrape包含和標簽,因為有時xml2json會需要它把HTML轉(zhuǎn)換成JSON。
5. xml2json – 把XML轉(zhuǎn)換成JSON
如名字所說,這工具就是把XML(HTML也是一種XML)轉(zhuǎn)換成JSON的輸出格式。因此,xml2json是連接scrape和jq之間的很好的橋梁。
- curl -s 'http://en.wikipedia.org/wiki/List_of_countries_and_territories_by_border/area_ratio' | scrape -be 'table.wikitable > tr:not(:first-child)' | xml2json | jq -c '.html.body.tr[] | {country: .td[1][], border: .td[2][], surface: .td[3][], ratio: .td[4][]}' | head
- {"ratio":"7.2727273","surface":"0.44","border":"3.2","country":"Vatican City"}
- {"ratio":"2.2000000","surface":"2","border":"4.4","country":"Monaco"}
- {"ratio":"0.6393443","surface":"61","border":"39","country":"San Marino"}
- {"ratio":"0.4750000","surface":"160","border":"76","country":"Liechtenstein"}
- {"ratio":"0.3000000","surface":"34","border":"10.2","country":"Sint Maarten (Netherlands)"}
- {"ratio":"0.2570513","surface":"468","border":"120.3","country":"Andorra"}
- {"ratio":"0.2000000","surface":"6","border":"1.2","country":"Gibraltar (United Kingdom)"}
- {"ratio":"0.1888889","surface":"54","border":"10.2","country":"Saint Martin (France)"}
- {"ratio":"0.1388244","surface":"2586","border":"359","country":"Luxembourg"}
- {"ratio":"0.0749196","surface":"6220","border":"466","country":"Palestinian territories"}
當然JSON數(shù)據(jù)之后可以輸入給json2csv。
6. sample – 用來debug
我寫的第二個工具是sample。(它是依據(jù)bitly的data_hacks寫的,bitly還有好多其他工具值得一看。)當你處理大量數(shù)據(jù)時,debug管道非常尷尬。這時,sample就會很有用。這個工具有三個用處:
- 逐行展示數(shù)據(jù)的一部分。
- 給在輸出時加入一些延時,當你的數(shù)據(jù)進來的時候有些延時,或者你輸出太快看不清楚時用這個很方便。
- 限制程序運行的時間。
下面的例子展現(xiàn)了這三個功能:
1
|
seq 10000 | sample -r 20% -d 1000 -s 5 | jq '{number: .}'
|
這表示,每一行有20%的機會被給到j(luò)q,沒兩行之間有1000毫秒的延遲,5秒過后,sample會停止。這些選項都是可選的。為了避免不必要的計算,請盡早sample。當你debug玩之后你就可以把它移除了。
7. Rio – 在處理中加入R
這篇文章沒有R就不完整。將R/Rscript加入處理不是很好理解,因為他們并沒有標準化輸入輸出,因此,我加入了一個命令行工具腳本,這樣就好理解了。
Rio這樣工作:首先,給標準輸入的CSV被轉(zhuǎn)移到一個臨時文件中,然后讓R把它讀進df中。之后,在-e中的命令被執(zhí)行。***,***一個命令的輸出被重定向到標準輸出中。讓我用一行命令展現(xiàn)這三個用法,對每個部分展現(xiàn)5個數(shù)字的總結(jié):
- curl -s 'https://raw.github.com/pydata/pandas/master/pandas/tests/data/iris.csv' > iris.csv
- < iris.csv Rio -e 'summary(df)'
- SepalLength SepalWidth PetalLength PetalWidth
- Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
- 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
- Median :5.800 Median :3.000 Median :4.350 Median :1.300
- Mean :5.843 Mean :3.054 Mean :3.759 Mean :1.199
- 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
- Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
- Name
- Length:150
- Class :character
- Mode :character
如果加入了-s選項,sqldf包會被引入,這樣CSV格式就會被輸出,這可以讓你之后用別的工具處理數(shù)據(jù)。
- < iris.csv Rio -se 'sqldf("select * from df where df.SepalLength > 7.5")' | csvlook
- |--------------+------------+-------------+------------+-----------------|
- | SepalLength | SepalWidth | PetalLength | PetalWidth | Name |
- |--------------+------------+-------------+------------+-----------------|
- | 7.6 | 3 | 6.6 | 2.1 | Iris-virginica |
- | 7.7 | 3.8 | 6.7 | 2.2 | Iris-virginica |
- | 7.7 | 2.6 | 6.9 | 2.3 | Iris-virginica |
- | 7.7 | 2.8 | 6.7 | 2 | Iris-virginica |
- | 7.9 | 3.8 | 6.4 | 2 | Iris-virginica |
- | 7.7 | 3 | 6.1 | 2.3 | Iris-virginica |
- |--------------+------------+-------------+------------+-----------------|
如果你用-g選項,ggplot2會被引用,一個叫g(shù)得帶有df的ggplot對象會被聲明。如果最終輸出是個ggplot對象,一個PNG將會被寫到標準輸出里。
- < iris.csv Rio -ge 'g+geom_point(aes(x=SepalLength,y=SepalWidth,colour=Name))' > iris.png
我制作了這個工具,為了可以在命令行中充分利用R的力量。當然它有很多缺陷,但至少我們不需要再學習gnuplot了。
別人建議的命令行工具
下面是其他朋友通過twitter和hacker news推薦的工具,謝謝大家。
- BigMLer by aficionado
- crush-tools by mjn
- csv2sqlite by dergachev
- csvquote by susi22
- data-tools repository by cgrubb
- feedgnuplot by dima55
- Grinder repository by @cgutteridge
- HDF5 Tools by susi22
- littler by @eddelbuettel
- mallet by gibrown
- RecordStream by revertts
- subsample by paulgb
- xls2csv by @sheeshee
- XMLStarlet by gav
結(jié)論
我介紹了七個我日常用來處理數(shù)據(jù)的命令行工具。雖然每個工具各有所長,我經(jīng)常是將它們與傳統(tǒng)工具(如grep, sed, 和awk)一起使用。將小工具結(jié)合起來使用組成一個大的流水線,這就是其用處所在。
不知你們對這個列表有什么想法,你們平時喜歡用什么工具呢。如果你們也做了什么好玩的工具,歡迎將其加入數(shù)據(jù)科學工具包data science toolbox。
如果你不認為自己能制作工具,也不用擔心,下次當你寫一個異乎尋常的命令行流水線時,記得將它放到一個文件里,加一個#!,加一些參數(shù),改成可執(zhí)行文件,你就做成一個工具啦~
雖然命令行工具的強大在獲取、處理和探索數(shù)據(jù)時不容小覷,在真正的探索、建模和理解翻譯數(shù)據(jù)時,你還是***在科學計算環(huán)境下進行。比如R或者IPython notebook+pandas。
如果感興趣,歡迎follow me on Twitter。
原文鏈接: jeroen janssens 翻譯: 大飛
譯文鏈接: http://blog.jobbole.com/54308/