這篇文章簡單紀錄xsv,一個處理csv檔案的command line工具的使用範例。
xsv是一個command line工具,專門用來處理csv檔案,方便使用者在處理資料或是觀察資料的時候可以迅速地得到想要的結果。
Usage:
xsv <command> [<args>...]
xsv [options]
Options:
--list List all commands available.
-h, --help Display this message
<command> -h Display the command help message
--version Print version info and exit
Commands:
cat Concatenate by row or column
count Count records
fixlengths Makes all records have same length
flatten Show one field per line
fmt Format CSV output (change field delimiter)
frequency Show frequency tables
headers Show header names
help Show this usage message.
index Create CSV index for faster access
input Read CSV data with special quoting rules
join Join CSV files
sample Randomly sample CSV data
search Search CSV data with regexes
select Select columns from CSV
slice Slice records from CSV
sort Sort CSV data
split Split CSV data into many files
stats Compute basic statistics
table Align CSV data into columns
上面是xsv的usage,底下會走過一遍在xsv的README.md裡面的範例,會更清楚各個指令的使用情況。
取得範例資料
在開始執行範例之前,會需要先準備一個csv檔案來作為指令的作用對象,在README.md裡面提供了一個範例資料,記載了世界上每個城市的人口。
curl -LO https://burntsushi.net/stuff/worldcitiespop.csv
安裝xsv
安裝xsv的方法可以參照官方文件裡面的說明,如果是mac的話可以直接使用底下的指令。
brew install xsv
如果是Windows或是Linux,xsv也有提供binary檔在GitHub上可以下載,下面的指令是以Linux為範例。
wget https://github.com/BurntSushi/xsv/releases/download/0.13.0/xsv-0.13.0-x86_64-unknown-linux-musl.tar.gz
tar zxvf xsv-0.13.0-x86_64-unknown-linux-musl.tar.gz
sudo mv xsv /usr/local/bin
查看csv的基本資料
csv裡面有哪些欄位
-> % xsv headers worldcitiespop.csv
1 Country
2 City
3 AccentCity
4 Region
5 Population
6 Latitude
7 Longitude
各個欄位的統計數據
-> % xsv stats --everything worldcitiespop.csv | xsv table
field type sum min max min_length max_length mean stddev median mode cardinality
Country Unicode ad zw 2 2 cn 234
City Unicode bab el ahmar Þykkvibaer 1 91 san jose 2351892
AccentCity Unicode Bâb el Ahmar ïn Bou Chella 1 91 San Antonio 2375760
Region Unicode 00 Z9 0 2 13 04 397
Population Integer 2289584999 7 31480498 0 8 47719.570633597126 302885.5592040396 10779 28754
Latitude Float 86294096.37312101 -54.933333 82.483333 1 12 27.188165808468785 21.95261384912504 32.4972221 51.15 1038349
Longitude Float 117718483.57958724 -179.9833333 180 1 14 37.08885989656418 63.223010459241635 35.28 23.8 1167162
在指令裡面的--everything
是把所有可以得到的統計數字都列出來,在這個例子裡面如果不下--everything
的話,欄位就會少了median、mode和cardinality,xsv stats
最後產生出來的會是csv的格式,為了在terminal上面比較好觀察,所以把結果pipe到xsv table
裡面讓它把結果排整齊。
csv有多少筆資料
-> % xsv count worldcitiespop.csv
3173958
查看csv的內容
查看csv的特定列數
-> % xsv slice worldcitiespop.csv -s 0 -e 5 | xsv table
Country City AccentCity Region Population Latitude Longitude
ad aixas Aixàs 06 42.4833333 1.4666667
ad aixirivali Aixirivali 06 42.4666667 1.5
ad aixirivall Aixirivall 06 42.4666667 1.5
ad aixirvall Aixirvall 06 42.4666667 1.5
ad aixovall Aixovall 06 42.4666667 1.4833333
在指令裡面的-s/--start
是開始的列數,這邊index是0-based的,所以第一筆資料的index是0,而-e/--end
是結束的列數,所給予的index不會包含在輸出裡面,可以想成會輸出的資料列數是[start, end)
。
在xsv slice
裡面還有提供-l/--len
的argument來讓使用者決定要輸出多少列。
-> % xsv slice worldcitiespop.csv -s 0 -l 6 | xsv table
Country City AccentCity Region Population Latitude Longitude
ad aixas Aixàs 06 42.4833333 1.4666667
ad aixirivali Aixirivali 06 42.4666667 1.5
ad aixirivall Aixirivall 06 42.4666667 1.5
ad aixirvall Aixirvall 06 42.4666667 1.5
ad aixovall Aixovall 06 42.4666667 1.4833333
ad andorra Andorra 07 42.5 1.5166667
如果只是想看特定某一列的話,可以用-i/--index
來看。
-> % xsv slice worldcitiespop.csv -i 1 | xsv table
Country City AccentCity Region Population Latitude Longitude
ad aixirivali Aixirivali 06 42.4666667 1.5
如果csv裡面有很多column的話,可以把指令後面的table換成flatten,改用直的方式印出來。
-> % xsv slice worldcitiespop.csv -s 0 -l 2 | xsv flatten
Country ad
City aixas
AccentCity Aixàs
Region 06
Population
Latitude 42.4833333
Longitude 1.4666667
#
Country ad
City aixirivali
AccentCity Aixirivali
Region 06
Population
Latitude 42.4666667
Longitude 1.5
查看特定column
-> % xsv select Country,AccentCity,Population worldcitiespop.csv | xsv sample 10 | xsv table
Country AccentCity Population
us Thomas Crossing
lk Egodagoda
ir Sarbandan
rs Malo Lukare
lv Polumyza Mazindritsa
ru Sovkhoznyy 3916
ne Balidey
mk (( Kisela Voda ))
br Japuim
ir Qal`ehgah-e Khalifeh
上面指令的xsv select
後面接的是column的名稱,這邊也可以用index來替代,不過這邊就是1-based的計數方式,所以在上面我們需要把Country,AccentCity,Population
替換成1,3,5
來得到一樣的column。
如果多個column有相同的名稱可以在後面用中括號來表示這個第幾個重複的column,像是xsv select 'Foo[2]'
就是拿第三個叫Foo
的column,而如果要抓取某個範圍內的column,可以用-
來選取中間所有的column,像是Country-Population
或1-5
,更多的操作方法可以看xsv select -h
裡面的說明。
每個value的出現次數
-> % xsv frequency worldcitiespop.csv --limit 3 | xsv table
field value count
Country cn 238985
Country ru 215938
Country id 176546
City san jose 328
City san antonio 320
City santa rosa 296
AccentCity San Antonio 317
AccentCity Santa Rosa 296
AccentCity Santa Cruz 281
Region 04 159916
Region 02 142158
Region 07 126867
Population (NULL) 3125978
Population 2310 12
Population 2230 11
Latitude 51.15 777
Latitude 51.083333 772
Latitude 51.116667 769
Longitude 23.8 484
Longitude 23.2 477
Longitude 23.05 476
這邊xsv frequency
會去計算每個column裡面的每一個value在這個csv裡面出現了幾次,而--limit
會限制取出現次數最多的前N名,如果想看頻率由小到大的排序,可以用-a/--asc
的option。
搜尋欄位的值
-> % xsv search -s Population '[0-9]' worldcitiespop.csv | xsv select Country,AccentCity,Population | xsv sample 10 | xsv table
Country AccentCity Population
cz Sumperk 29604
co Vianí 1586
ph La Curva 3359
fr Eaubonne 23739
in Kamareddi 71049
ru Ust-Kulom 5205
us Brent 22735
ph Lupao 11000
ro Caraula 2628
ph Bacnar 4606
-s/--select
可以指定要搜尋的是哪一個column,而後面搜尋的pattern是regular expression,如果想要排除有比對到的結果,可以用-v/--invert-match
,xsv search
會把所有有比對到的列都印出來變成csv檔,所以如果要只顯示部分的欄位就需要再使用xsv select
或是xsv slice
做處理。
join兩個csv
在上面的例子裡面,如果我們想要知道每個Country的縮寫實際代表的國家是哪個的話,可以透過查表的方式來得到,底下的指令會下載一個csv檔,裡面記載著國家縮寫的全稱是什麼。
curl -LO https://gist.githubusercontent.com/anonymous/063cb470e56e64e98cf1/raw/98e2589b801f6ca3ff900b01a87fbb7452eb35c7/countrynames.csv
-> % xsv headers countrynames.csv
1 Abbrev
2 Country
我們也可以使用join的方式來直接把所有的縮寫都轉成全稱。
-> % xsv join --no-case Abbrev countrynames.csv Country worldcitiespop.csv | xsv sample 10 | xsv table
Abbrev Country Country City AccentCity Region Population Latitude Longitude
CO Colombia co santa marta Santa Marta 28 3.883889 -75.102222
LV Latvia lv kozes Kozes 10 56.2 25.7
TN Tunisia tn bir bou rekba Bir Bou Rekba 19 36.434824 10.565897
LA Laos la ban poung Ban Poung 22 19.928056 100.608611
GE Georgia ge zakvi Zakvi 06 41.5063889 43.4997222
MZ Mozambique mz gube Gubé 04 -26.2833333 32.5666667
PE Peru pe cruz de callana Cruz de Callana 11 -13.75 -75.9333333
MZ Mozambique mz maguezane Maguezane 03 -21.5166667 34.6375
TH Thailand th ban tang pra Ban Tang Pra 35 14.678472 100.351278
LA Laos la ban xiangkheng Ban Xiangkheng 16 21.333333 100.883333
在xsv join
裡面,需要先把想要join的key擺在前面,後面再接csv檔。除了上面的inner join以外,xsv還有支援left join、right join等,可以看xsv join -h
裡面的說明。
在上面的結果裡面,如果我們只想要保留國家的全稱就好,想把join的key都拿掉的話,可以再過一個xsv select '!Abbrev,Country[1]'
,把除了Abbrev和第二個Country以外的全部欄位都選出來。
-> % xsv join --no-case Abbrev countrynames.csv Country worldcitiespop.csv | xsv select '!Abbrev,Country[1]' | xsv sample 10 | xsv table
Country City AccentCity Region Population Latitude Longitude
Peru cachisama Cachisama 05 -13.1166667 -74.3
Bosnia and Herzegovina | Bosnia gecet Gecet 01 44.5666667 16.1005556
China caihuaqiao Caihuaqiao 07 27.035278 119.777222
Pakistan kothung Kothung 07 35.384052 75.74772
Pakistan dhok waraich Dhok Waraich 04 33.727099 72.242949
Russian Federation | Russia yasenok Yasenok 10 53.218388 32.851209
Philippines padaraonan Padaraonan J3 10.4919 122.4906
Indonesia gunungaseupan Gunungaseupan 30 -7.039722 107.505278
Colombia dificil Dificil 38 9.849747 -74.236267
Ukraine lesnichevka Lesnichëvka 23 48.613614 28.180124
加速xsv的計算
xsv支援先對csv檔做index,來讓xsv的其他操作像是stats
、slice
等可以變得更快。
-> % xsv index worldcitiespop.csv
執行完上面的指令以後會產生一個wordcitiespop.csv.idx的檔案,接下來在執行其他操作的時候就會自動加速了,不過如果原本的檔案內容有被更動過的話,會需要再重新製作一個index檔。