第2章: UNIXコマンド
この章では、以下のデータを使用します。
popular-names.txt
アメリカで生まれた赤ちゃんの「名前」「性別」「人数」「年」をタブ区切り形式で格納したファイル.
またここでは、Google Colaboratoryを使用しています。
10. 行数のカウント
行数をカウントせよ.確認にはwcコマンドを用いよ.
requestsを用いた解
import requests
url = "https://nlp100.github.io/data/popular-names.txt"
try:
r = requests.get(url)
print(sum([1 for _ in r.iter_lines()]))
except requests.exceptions.RequestException as err:
print(err)
<出力>
2780
Pandasを使用した解
import numpy as np
import pandas as pd
datas = pd.read_csv("https://nlp100.github.io/data/popular-names.txt",sep='\t',header=None)
datas.head()
print(datas.shape[0])
<出力>
2780
wcコマンドによる解
!wget "https://nlp100.github.io/data/popular-names.txt"
%cat "popular-names.txt" | wc -l
<出力>
--2020-08-10 05:08:12-- https://nlp100.github.io/data/popular-names.txt
Resolving nlp100.github.io (nlp100.github.io)... 185.199.108.153, 185.199.109.153, 185.199.110.153, ...
Connecting to nlp100.github.io (nlp100.github.io)|185.199.108.153|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 55026 (54K) [text/plain]
Saving to: ‘popular-names.txt’
popular-names.txt 100%[===================>] 53.74K --.-KB/s in 0.03s
2020-08-10 05:08:12 (2.03 MB/s) - ‘popular-names.txt’ saved [55026/55026]
2780
11. タブをスペースに置換
タブ1文字につきスペース1文字に置換せよ.確認にはsedコマンド,trコマンド,もしくはexpandコマンドを用いよ.
直接ダウンロードストリームを変換して表示
import requests
url = "https://nlp100.github.io/data/popular-names.txt"
try:
r = requests.get(url)
print(r.text.replace("\t"," "))
except requests.exceptions.RequestException as err:
print(err)
<出力>
Mary F 7065 1880
Anna F 2604 1880
Emma F 2003 1880
・・・
ダウンロードしたファイルを変換して表示
with open("popular-names.txt", 'r') as f:
lines = f.read() # readlines()で読むと改行コードが付加されるため、ここではread()を使用。
print(lines.replace("\t", " "))
<出力>
Mary F 7065 1880
Anna F 2604 1880
Emma F 2003 1880
・・・
sedを使用
!sed "s/\t/ /g" "popular-names.txt" | head -n 3
<出力>
Mary F 7065 1880
Anna F 2604 1880
Emma F 2003 1880
12. 1列目をcol1.txtに,2列目をcol2.txtに保存
各行の1列目だけを抜き出したものをcol1.txtに,2列目だけを抜き出したものをcol2.txtとしてファイルに保存せよ.確認にはcutコマンドを用いよ.
import numpy as np
import pandas as pd
datas = pd.read_csv("https://nlp100.github.io/data/popular-names.txt",sep='\t',header=None)
datas.columns=['Name','Sex','Count','Year']
datas.to_csv(path_or_buf="col1.txt",sep=" ",columns=["Name"],header=False,index=False,)
datas.to_csv(path_or_buf="col2.txt",sep=" ",columns=["Sex"],header=False,index=False,)
<確認1>
%cat col1.txt | head -n 5
<出力>
Mary
Anna
Emma
Elizabeth
Minnie
<確認2>
%cat col2.txt | head -n 5
<出力>
F
F
F
F
F
sedでの確認
!cut -f 1 "popular-names.txt" | head -n 3
!cut -f 2 "popular-names.txt" | head -n 3
<出力>
Mary
Anna
Emma
F
F
F
13. col1.txtとcol2.txtをマージ
12で作ったcol1.txtとcol2.txtを結合し,元のファイルの1列目と2列目をタブ区切りで並べたテキストファイルを作成せよ.確認にはpasteコマンドを用いよ.
import pandas as pd
data1 = pd.read_csv('col1.txt',header=None)
data2 = pd.read_csv('col2.txt',header=None)
data1['Sex'] = data2[0]
data1.to_csv('2col_data.txt',sep="\t", header=False, index=False)
<確認>
%cat '2col_data.txt' | head -n 3
Mary F
Anna F
Emma F
pasteコマンドによる確認
!paste -d "\t" 'col1.txt' 'col2.txt' | head -n 3
<出力>
Mary F
Anna F
Emma F
14. 先頭からN行を出力
自然数Nをコマンドライン引数などの手段で受け取り,入力のうち先頭のN行だけを表示せよ.確認にはheadコマンドを用いよ.
pythonで実装
def headEx(n, strPath):
with open(strPath) as f:
data = f.readlines()
f.close()
ret=""
for i,line in enumerate(data):
if i> (n-1):
break
else:
ret += line
return ret
print(headEx(4,'2col_data.txt'))
<出力>
Mary F
Anna F
Emma F
Elizabeth F
headコマンドで確認
%cat '2col_data.txt' | head -n 4
<出力>
Mary F
Anna F
Emma F
Elizabeth F
15. 末尾のN行を出力
自然数Nをコマンドライン引数などの手段で受け取り,入力のうち末尾のN行だけを表示せよ.確認にはtailコマンドを用いよ.
pythonで実装
def tailEx(n, strPath):
with open(strPath) as f:
data = f.readlines()
ret=""
if len(data) < n:
n=len(data)
for line in data[-n-1:-1]:
ret += line
return ret
print(tailEx(4,'2col_data.txt'))
<出力>
Benjamin M
Elijah M
Lucas M
Mason M
tailコマンドで確認
%cat '2col_data.txt' | tail -n 4
<出力>
Elijah M
Lucas M
Mason M
Logan M
16. ファイルをN分割する
自然数Nをコマンドライン引数などの手段で受け取り,入力のファイルを行単位でN分割せよ.同様の処理をsplitコマンドで実現せよ.
pythonで実装
def splitN(N, strPath):
with open(strPath) as f:
data = f.readlines()
print(len(data))
if N<1 or len(data)<N:
return data
rowNum = int(len(data) / N)
print("rowNum = " + str(rowNum))
for cnt in range(N):
ed = (cnt+1)*rowNum
if cnt==(N-1):
ed = len(data)
ret=""
for line in data[cnt*rowNum:ed]:
ret += line
outPath = strPath.replace('.txt', '__' + str(cnt)+'.txt')
with open(outPath, 'w') as f:
f.write(ret)
splitN(3,'2col_data.txt')
<出力>
2780
rowNum = 926
%ls
2col_data__0.txt 2col_data__2.txt col1.txt popular-names.txt
2col_data__1.txt 2col_data.txt col2.txt sample_data/
%cat "2col_data__0.txt" | wc -l
%cat "2col_data__1.txt" | wc -l
%cat "2col_data__2.txt" | wc -l
926
926
928
splitコマンドで確認
!split --number=3 "2col_data.txt" # 3つに分割
%ls
作成されたファイルは自動命名され、xaa,xab,xacという名前で保存されている。
2col_data__0.txt 2col_data__2.txt col1.txt popular-names.txt xaa xac
2col_data__1.txt 2col_data.txt col2.txt sample_data/ xab
分割されたファイルの行数を確認
%cat "xaa" | wc -l
%cat "xab" | wc -l
%cat "xac" | wc -l
947
940
893
行数が異なっている。
%ls -la x*
-rw-r--r-- 1 root root 8359 Aug 12 06:13 xaa
-rw-r--r-- 1 root root 8359 Aug 12 06:13 xab
-rw-r--r-- 1 root root 8360 Aug 12 06:13 xac
splitで単純に個数指定で分割すると、データサイズで等分されるようである。
17. 1列目の文字列の異なり
1列目の文字列の種類(異なる文字列の集合)を求めよ.確認にはcut, sort, uniqコマンドを用いよ.
pythonで実装
import pandas as pd
datas = pd.read_csv("https://nlp100.github.io/data/popular-names.txt",sep='\t',header=None)
print(list(set(datas[0]))[0:3])
print(len(set(datas[0])))
<出力>
['Nancy', 'Rebecca', 'Ethan']
136
uniqコマンドで確認
!cut -f 1 "popular-names.txt" | sort | uniq | wc -l
136
cutコマンドで1列目を取り出し、ソートしてからuniqで重複を除去し、wcで行数をカウントしている。
uniqでは、連続した重複しか重複とみなされないため、sortしてから重複除去を行っている。
18. 各行を3コラム目の数値の降順にソート
各行を3コラム目の数値の逆順で整列せよ(注意: 各行の内容は変更せずに並び替えよ).確認にはsortコマンドを用いよ(この問題はコマンドで実行した時の結果と合わなくてもよい).
pythonで実装
# 17からのつづき
datas = datas.sort_values(by=2, ascending=False)
datas.head(5)
<出力>
0 1 2 3
1340 Linda F 99689 1947
1360 Linda F 96211 1948
1350 James M 94757 1947
1550 Michael M 92704 1957
1351 Robert M 91640 1947
sortコマンドで確認
sortコマンドのオプション
-k3 3列目
-n 数値として比較
-r 逆順にソート
-t 区切り文字指定(タブ指定は-t$'\t')
!cat "popular-names.txt" | sort -k3rn -t$'\t' | head -n 5
<出力>
Linda F 99689 1947
Linda F 96211 1948
James M 94757 1947
Michael M 92704 1957
Robert M 91640 1947
19. 各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる
各行の1列目の文字列の出現頻度を求め,その高い順に並べて表示せよ.確認にはcut, uniq, sortコマンドを用いよ.
pythonによる実装
import pandas as pd
datas = pd.read_csv("https://nlp100.github.io/data/popular-names.txt",sep='\t',header=None)
print(datas[0].value_counts())
<出力>
James 118
William 111
John 108
Robert 108
Mary 92
...
Laura 1
Rachel 1
Lori 1
Crystal 1
Scott 1
Name: 0, Length: 136, dtype: int64
sortコマンドでの確認
!cut -f 1 "popular-names.txt" | sort | uniq -c | sort -k1rn | head -n 5
<出力>
118 James
111 William
108 John
108 Robert
92 Mary