1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

言語処理100本ノック:第2章 UNIXコマンドの基礎(pandas使用)

Posted at

言語処理100本ノック 2015「第2章: UNIXコマンドの基礎」の記録です。
第2章はCSVファイルの操作関連です。1年以上前にやった内容の復習です。やった当時は「UNIXコマンド使わないでPythonでいいじゃん」くらいに思っていましたが、大きいサイズのファイルを扱うときはUNIXコマンドの方がだいたい速いんですよね。UNIXコマンドは覚えておいて損がないです。
今回、Python部分についてはPandasパッケージを多く使っています。CSVのような行列系データの扱いにはほんとに便利です。

環境

種類 バージョン 内容
OS Ubuntu18.04.01 LTS 仮想で動かしています
pyenv 1.2.15 複数Python環境を使うことがあるのでpyenv使っています
Python 3.6.9 pyenv上でpython3.6.9を使っています
3.7や3.8系を使っていないことに深い理由はありません
パッケージはvenvを使って管理しています

第2章: UNIXコマンドの基礎

学習内容

研究やデータ分析において便利なUNIXツールを体験します.これらの再実装を通じて,プログラミング能力を高めつつ,既存のツールのエコシステムを体感します.

head, tail, cut, paste, split, sort, uniq, sed, tr, expand

ノック内容

hightemp.txtは,日本の最高気温の記録を「都道府県」「地点」「℃」「日」のタブ区切り形式で格納したファイルである.以下の処理を行うプログラムを作成し,hightemp.txtを入力ファイルとして実行せよ.さらに,同様の処理をUNIXコマンドでも実行し,プログラムの実行結果を確認せよ.

10. 行数のカウント

行数をカウントせよ.確認にはwcコマンドを用いよ.

010.行数のカウント.ipynb

Pythonだとreadlinesで一気に読むのが一番速いはず(たいして調べていません)。

Python部分
print(len(open('./hightemp.txt').readlines()))
ターミナル出力結果
24

wcはWord Countの略でしょう。-lオプションで改行コードをカウントします。大きなファイルはテキストエディタで開くだけでも時間がかかるので重宝します

Bash部分
wc hightemp.txt -l
ターミナル出力結果
24 hightemp.txt

11.タブをスペースに置換

タブ1文字につきスペース1文字に置換せよ.確認にはsedコマンド,trコマンド,もしくはexpandコマンドを用いよ.

011.タブをスペースに置換.ipynb

replace関数を使って置換します。改行しないと結果が見にくいのでpprint使っています。

Python部分
from pprint import pprint

with open('./hightemp.txt') as f:
    pprint([line.replace('\t', ' ')for line in f])
ターミナル出力結果
['高知県 江川崎 41 2013-08-12\n',
 '埼玉県 熊谷 40.9 2007-08-16\n',
 '岐阜県 多治見 40.9 2007-08-16\n',

中略

 '山梨県 大月 39.9 1990-07-19\n',
 '山形県 鶴岡 39.9 1978-08-03\n',
 '愛知県 名古屋 39.9 1942-08-02\n']

sedは文字列置換、行の削除ができます。このコマンドを実行では、ターミナルに結果を出すだけなのでファイル中身が更新されるわけではありません。「【 sed 】 文字列の置換,行の削除を行う」を参考にしました。

Bash部分
sed 's/\t/ /g' ./hightemp.txt
ターミナル出力結果
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16

中略

山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02

12.1列目をcol1.txtに,2列目をcol2.txtに保存

各行の1列目だけを抜き出したものをcol1.txtに,2列目だけを抜き出したものをcol2.txtとしてファイルに保存せよ.確認にはcutコマンドを用いよ.

012.1列目をcol1.txtに,2列目をcol2.txtに保存.ipynb

Pandasを使いました。パラメータusecolsで読み込む列を1と2列目に限定しています。便利ですね。

Python部分
import pandas as pd

df = pd.read_table('./hightemp.txt', header=None, usecols=[0, 1])
df[0].to_csv('012.col1.txt',index=False, header=False)
df[1].to_csv('012.col2.txt',index=False, header=False)

cutで中身を確かめます。「【 cut 】コマンド――行から固定長またはフィールド単位で切り出す」を参考にしました。

Bash部分
cut -f 1 ./hightemp.txt
cut -f 2 ./hightemp.txt
ターミナル出力結果(1列目)
高知県
埼玉県
岐阜県

中略

山梨県
山形県
愛知県
ターミナル出力結果(2列目)
江川崎
熊谷
多治見
山形

中略

大月
鶴岡
名古屋

13.col1.txtとcol2.txtをマージ

12で作ったcol1.txtとcol2.txtを結合し,元のファイルの1列目と2列目をタブ区切りで並べたテキストファイルを作成せよ.確認にはpasteコマンドを用いよ.

013.col1.txtとcol2.txtをマージ.ipynb

pandasで2つのファイルを読んでつなげています。

Python部分
import pandas as pd

result = pd.read_csv('012.col1.txt', header=None)
result[1] = pd.read_csv('012.col2.txt', header=None)

result.to_csv('013.col1_2.txt', index=False, header=None, sep='\t')

「pasteコマンドについて詳しくまとめました 【Linuxコマンド集】」を参考にしました。出力結果は省略します。

Bash部分
paste 012.col1.txt 012.col2.txt

14.先頭からN行を出力

自然数Nをコマンドライン引数などの手段で受け取り,入力のうち先頭のN行だけを表示せよ.確認にはheadコマンドを用いよ.

014.先頭からN行を出力.ipynb

input関数で引数を受け取っています。

Python部分
from pprint import pprint

n = int(input('N Lines--> '))

with open('hightemp.txt') as f:
    for i, line in enumerate(f):
        if i < n:
            pprint(line)
        else:
            break
ターミナル出力結果
'高知県\t江川崎\t41\t2013-08-12\n'
'埼玉県\t熊谷\t40.9\t2007-08-16\n'
'岐阜県\t多治見\t40.9\t2007-08-16\n'

「ファイルの先頭から表示するheadコマンドの詳細まとめ【Linuxコマンド集】」を参考にしました。

Bash部分
head hightemp.txt -n 3
ターミナル出力結果
高知県	江川崎	41	2013-08-12
埼玉県	熊谷	40.9	2007-08-16
岐阜県	多治見	40.9	2007-08-16

15.末尾のN行を出力

自然数Nをコマンドライン引数などの手段で受け取り,入力のうち末尾のN行だけを表示せよ.確認にはtailコマンドを用いよ.

015.末尾のN行を出力.ipynb

これは結構迷いました。ファイルが大きい場合に全件読み込むのが嫌だったのでLinuxのheadで全件を確認した後にlinecacheパッケージを使おうかとも思いましたが、だったらtailでいいじゃん状態です。結局readlines使いました。

Python部分
from pprint import pprint

n = int(input('N Lines--> '))

with open('hightemp.txt') as f:
    pprint(f.readlines()[-n:])
ターミナル出力結果
['山梨県\t大月\t39.9\t1990-07-19\n',
 '山形県\t鶴岡\t39.9\t1978-08-03\n',
 '愛知県\t名古屋\t39.9\t1942-08-02\n']
Bash部分
tail hightemp.txt -n 3
ターミナル出力結果
山梨県	大月	39.9	1990-07-19
山形県	鶴岡	39.9	1978-08-03
愛知県	名古屋	39.9	1942-08-02

16.ファイルをN分割する

自然数Nをコマンドライン引数などの手段で受け取り,入力のファイルを行単位でN分割せよ.同様の処理をsplitコマンドで実現せよ.

016.ファイルをN分割する.ipynb

mathパッケージのceil関数を使って商を切り上げています。
ファイル書き出しはwritelines関数で一括追加しています。

Python部分
import math

n = int(input('N spilits--> '))

with open('./hightemp.txt') as f:
    lines = f.readlines()

unit = math.ceil(len(lines) / n)

for i in range(0, n):
    with open('016.hightemp{}.txt'.format(i), 'w') as out_file:
        out_file.writelines(lines[i*unit:(i+1)*unit])

「【 split 】コマンド――ファイルを分割する」を参考にしました。

Bash部分
split -n 3 -d hightemp.txt 016.hightemp-u

17.1列目の文字列の異なり

1列目の文字列の種類(異なる文字列の集合)を求めよ.確認にはsort, uniqコマンドを用いよ.

017.1列目の文字列の異なり.ipynb

pandasunique関数使いました。pandasは、この手の処理は非常に楽にできます。

Python部分
import pandas as pd

df = pd.read_table('hightemp.txt', header=None, usecols=[0])

print(df[0].unique())
ターミナル出力結果
['高知県' '埼玉県' '岐阜県' '山形県' '山梨県' '和歌山県' '静岡県' '群馬県' '愛知県' '千葉県' '愛媛県' '大阪府']

「sortコマンドについて詳しくまとめました 【Linuxコマンド集】」を参考にしました。

Bash部分
cut --fields=1 hightemp.txt | sort | uniq > result.txt
ターミナル出力結果
千葉県
和歌山県
埼玉県
大阪府
山形県
山梨県
岐阜県
愛媛県
愛知県
群馬県
静岡県
高知県

18.各行を3コラム目の数値の降順にソート

各行を3コラム目の数値の逆順で整列せよ(注意: 各行の内容は変更せずに並び替えよ).確認にはsortコマンドを用いよ(この問題はコマンドで実行した時の結果と合わなくてもよい).

018.各行を3コラム目の数値の降順にソート.ipynb

pandassort_values関数使いました。

Python部分
import pandas as pd

df = pd.read_table('hightemp.txt', header=None, usecols=[0])

print(df.sort_values(2, ascending=False))
ターミナル出力結果
       0     1     2           3
0    高知県   江川崎  41.0  2013-08-12
2    岐阜県   多治見  40.9  2007-08-16
1    埼玉県    熊谷  40.9  2007-08-16

中略

21   山梨県    大月  39.9  1990-07-19
22   山形県    鶴岡  39.9  1978-08-03
23   愛知県   名古屋  39.9  1942-08-02
Bash部分
sort hightemp.txt -k 3 -n -r
ターミナル出力結果
高知県	江川崎	41	2013-08-12
岐阜県	多治見	40.9	2007-08-16
埼玉県	熊谷	40.9	2007-08-16

中略

大阪府	豊中	39.9	1994-08-08
埼玉県	鳩山	39.9	1997-07-05
千葉県	茂原	39.9	2013-08-11

19.各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる

各行の1列目の文字列の出現頻度を求め,その高い順に並べて表示せよ.確認にはcut, uniq, sortコマンドを用いよ.

019.各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる.ipynb

pandasvalue_counts関数使いました。

Python部分
import pandas as pd

df = pd.read_table('hightemp.txt', header=None, usecols=[0])

print(df[0].value_counts(ascending=False))
ターミナル出力結果
埼玉県     3
山梨県     3
山形県     3

中略

愛媛県     1
高知県     1
大阪府     1
Bash部分
cut -f 1 hightemp.txt | sort | uniq -c | sort -r
ターミナル出力結果
      3 群馬県
      3 山梨県
      3 山形県

中略

      1 愛媛県
      1 大阪府
      1 和歌山県
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?