CSVKIT——處理csv檔案的瑞士軍刀

weixin_33850890發表於2017-04-02

統計和資料處理都離不開csv檔案,一般來說,操作csv都是依賴第三方軟體,如Excel、Matlab這樣的;也可以自己程式設計,用Python、Perl等等,直接操作檔案比較麻煩。

但對簡單的處理,用大體量的軟體或是寫一段程式碼有點殺雞用牛刀的感覺,這時,csvkit就有用武之地。

開始

安裝csvkit

安裝csvkit很簡單:

pip3 install csvkit

我的系統是Python3.6,所以用pip3來安裝,如果還在用Python2.7,就用pip install csvkit來進行安裝。

為了方便後面的測試和解釋,建議從官方下載測試樣本檔案:

curl -L -O  https://raw.githubusercontent.com/wireservice/csvkit/master/examples/realdata/ne_1033_data.xlsx

in2csv:Excel的殺手

下載的樣本檔案是一個Excel檔案,誰願意為了僅僅看兩行資料而等待Excel漫長的啟動介面呢?所以首先要將它轉換為csv檔案,轉換也不用開啟Excel,一條命令:

in2csv ne_1033_data.xlsx > data.csv

>是shell的重定向符,如果不重定向,in2csv會將轉換之後的內容輸出到控制檯顯示,現在我希望能儲存為csv檔案便於後續的操作,所以就將內容輸出定向到data.csv檔案中。

接下來看看data.csv的內容吧:

cat data.csv
1749344-28465bba93cdca4f.png
cat 的輸出原始而粗糙

csv檔案內容有了,如果用cat的方式來看,既不方便也不美觀,接下來我們用另一個工具檢視

csvlook:資料潛望鏡

這個檔案有多少行呢,用cat data.csv | wc -l看了一下,有1037行,所以一屏肯定是看不完的,需要分頁檢視,而分頁功能在類Unix系統上有現成的less可用。

csvlook data.csv | less -S
csvlook

這樣的顯示就好多了,還可以方向鍵滾動檢視,q退出,/搜尋,等一系列less專用操作。

csvcut:資料手術刀

既然名字中帶了一個cut,聰明的你肯定猜到了它的用途,不過放心,所有的操作都不會修改輸入(原始檔案),只會影響輸出。

先看看這個資料有哪些列

csvcut -n data.csv
csvcut檢視列標題

可以看到,總共有14列,在輸出資訊中,前面的數字是數字索引位置,預設是從1開始計數,後面的是列名稱,我想只看感興趣的幾列資料(在這裡我為了演示,只顯示4行資料,所以加了head進行輸出行數限定):

csvcut -c 2,5,6 data.csv | head -n 5
選擇列

可以看到既可以用數字作為索引,也可以用列名稱作為索引,所以上面的指令和下面這個指令是等價的

csvcut -c county,item_name,quantity data.csv | head -n 5

用管道進行組合

上面的輸出不錯,能否再顯示得美觀一點呢?答案是肯定的,將命令用管道組合起來就行了

csvcut -c county,item_name,quantity data.csv | csvlook | head
Putting it together with pipes

|管道是類Unix平臺上的強大能力,如果不關心中間結果,甚至可以從頭到尾都用管道進行連線,例如上面的命令改成如下方式,也是一樣的結果

in2csv ne_1033_data.xlsx | csvcut -c county,item_name,quantity | csvlook | head

這樣就省去了生成data.csv檔案的中間過程。

資料分析

csvstat:無程式碼亦統計

使用csvlookcsvcut檢視資料的切片只是探索資料的開始,在實踐中,通常還需要一些計算和統計,csvstat的設計靈感來自程式語言 “R”summary()統計,它可以統計彙總一個CSV檔案中的資料列。

csvcut -c county,acquisition_cost,ship_date data.csv | csvstat
命令列的*Summary*

不知道你有沒有統計學基礎?如果有的話,應該一目瞭然,唯一值、最小值、最大值、總計、均值、中位值、標準差……,大部分情況下夠用了:)

csvgrep:找到需要的資料

僅僅按照列的方式過濾還是比較弱,還需要按照內容進行過濾,這時csvgrep就派上用場,例如,我們只想看蘭開斯特的資料。

csvcut -c county,item_name,total_cost data.csv | csvgrep -c county -m LANCASTER | csvlook
基於列和內容過濾

csvgrep還支援正規表示式,關於正規表示式的討論有點超出本篇範圍,有興趣可以檢視系統工具grep的手冊。

csvsort:秩序

前面顯示出來的內容都很少,實際中往往都有成千上萬行,所以排序功能很重要,我們試一下用csvsorttotal_cost列進行遞減順序:

csvcut -c county,item_name,total_cost data.csv | csvgrep -c county -m LANCASTER | csvsort -c total_cost -r | csvlook
按照總成本遞減排列

寶刀屠龍

csvjoin:關聯資料

在上面的資料中,有各個地區的武器裝備資訊,接下來想了解一個問題——裝備有武器的地區中,哪裡的人口最少?

原來的資料表不包含人口數量,所以下載一個包含人口資訊的資料:

curl -L -O https://raw.githubusercontent.com/wireservice/csvkit/master/examples/realdata/acs2012_5yr_population.csv
各地區的人口資料

兩個資料表都包含fips欄位,我們可以用這個欄位來連線兩個資料:

csvjoin -c fips data.csv acs2012_5yr_population.csv > joined.csv
csvcut -c county,item_name,total_population joined.csv | csvsort -c total_population | csvlook | head
兩個小地區也有5.56毫米突擊步槍

csvstack:合併資料

資料經常會分散在不同地方,這時希望將一堆的csv檔案合併成一個資料檔案,csvstack可以幫助達成這個目標,一般來說csvstack需要同列同名的資料才可以合併。但是你知道,有時候即使兩個csv檔案有稍微的不同,也可以通過csvcut的列選擇來獲得同列同名的資料表。

# 獲得堪薩斯州的測試資料
curl -L -O https://raw.githubusercontent.com/wireservice/csvkit/master/examples/realdata/ks_1033_data.csv
# 使用相同的檔名命名規則
in2csv ne_1033_data.xlsx > ne_1033_data.csv
# 合併兩個檔案到region.csv中
csvstack ne_1033_data.csv ks_1033_data.csv > region.csv
# 檢視部分列的統計資訊
csvstat -c state,acquisition_cost region.csv
合併兩個州的資料

csvsql, sql2csv:必殺技

有時,僅僅命令列是不夠的,需要用SQL來進行資料的操作,csvsqlsql2csv就提供了資料庫和csv之間的橋樑。

例如,我想將現在的csv檔案轉為資料庫表

csvsql -i sqlite joined.csv
Sqlite資料表

當然,我們可以一步到位,直接建立一個本地資料庫:

csvsql --db sqlite:///leso.db --insert joined.csv
建立本地資料庫檔案leso.db

接下來,就可以利用資料庫軟體對這個資料庫進行常規的SQL查詢,當然也可以用CSVKIT提供的小工具sql2csv來進行查詢。

sql2csv --db sqlite:///leso.db --query "select * from joined where total_population<1000;" | csvcut -c state,county,total_population | csvlook
SQL 查詢

如果SQL查詢使用不頻繁,何不直接在csv上執行SQL查詢呢?

csvsql --query "select county,item_name,quantity from joined where quantity == 5;" joined.csv 2>/dev/null | csvlook
直接在csv檔案上執行SQL查詢

總結

由於我經常做資料處理的計算,所以磁碟上總是有大量的csv檔案,用普通的文字編輯器開啟非常緩慢不說,還不方便查詢和檢視,有了這套工具確實方便了很多。此外,它對中文的處理也還行,檔案設定為UTF-8編碼就好。

相關文章