言語処理100本ノック 2020 第2章 後半
第2章 UNIXコマンドの後半(15-19まで)解説書きます。
いい感じにpandas慣れてきて楽しくなってきた。
目次
- 15. 末尾のN行を出力
- 16. ファイルをN分割する
- 17. 1列目の文字列の異なり
- 18. 各行を3コラム目の数値の降順にソート
- 19. 各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる
この章で使うファイル
タブ区切りでアメリカの赤ちゃんの名前、性別、人数、生まれた年が記録された
テキストファイル。
$ head popular-names.txt Mary F 7065 1880 Anna F 2604 1880 Emma F 2003 1880 Elizabeth F 1939 1880 Minnie F 1746 1880 Margaret F 1578 1880 Ida F 1472 1880 Alice F 1414 1880 Bertha F 1320 1880 Sarah F 1288 1880
15. 末尾のN行を出力
ほとんど14と一緒。先頭か末尾かの違いだけ。
ポイント
- pandas.DataFrameから末尾のn行を取り出す時、スライスdf[-n:]か df.tail(n) を使う
解答コマンド
最初の3行だけほしい時の場合。
tailコマンドは-n
オプションで表示したい行数を指定できる。
デフォルトは先頭10行が表示される。
tail -n 3 popular-names.txt
解答スクリプト
引数はstr型で返ってくるので、intにキャストする。(ポカミスするので2度言いました)
# coding:utf-8 import argparse import pandas as pd def arg(): parser = argparse.ArgumentParser(description='自然数') parser.add_argument('n', help='num') args = parser.parse_args() return(args.n) def main(): path = './popular-names.txt' n = int(arg()) df = pd.read_csv(path, sep='\t', header=None) print(df[-n:]) # print(df.tail(n)) if __name__ == "__main__": main()
参考記事
16. ファイルをN分割する
問題文色々調べた結果、numpyを召喚した。
numpyもそこまで慣れてないので、kaggleにあった100本ノックをやりたい。
ポイント
- pandas.DataFrameをn分割する際、numpy.split(df, n)を使う
解答コマンド
なんかこれっぽい解答を思いつかなかった。
splitコマンドの-l
オプションで、分割する行数を指定できる。
分割後のファイル名は、指定がなければ、xaa, xab, xac...というように命名される。
今回は1000行ずつ分割した。
split -l 1000 popular-names.txt
解答スクリプト
# coding:utf-8 import argparse import pandas as pd import numpy as np def arg(): parser = argparse.ArgumentParser(description="自然数") parser.add_argument('n', help='num') args = parser.parse_args() return args.n def main(): path = './popular-names.txt' n = int(arg()) df = pd.read_csv(path, sep='\t', header=None) chunks = np.split(df, n) for i in range(n): print(chunks[i]) if __name__ == "__main__": main()
参考記事
17. 1列目の文字列の異なり
よくありそうな重複削除系問題。
ポイント
- pandas.DataFrameでもsetが使える
解答コマンド
昇順にソートしてからuniqコマンドで重複削除をする。鉄則。
cut -f 1 popular-names.txt | sort | uniq
解答スクリプト
# coding:utf-8 import pandas as pd path = './popular-names.txt' df = pd.read_csv(path, sep='\t', header=None) df.columns = ['Name', 'Sex', 'Count', 'Year'] letter = set(df['Name']) print(letter)
18. 各行を3コラム目の数値の降順にソート
これもよくありそうな処理。pandas使いになるには避けて通れない。
ポイント
- pandas.DataFrameをソートする時、df.sort_values('基準のカラム名') を使う
- 降順ソートの場合、df.sort_values('基準のカラム名', ascending=False)になる
- ソート後にdf.reset_index( )インデックスの振り直しが可能。
- drop=True をつけると、振り直し前のインデックスを削除できる
- inplace=True をつけると、新しいオブジェクトが生成される
解答コマンド
sortコマンドの-r
オプションで降順、-n
で数値として並べ替え指定、
-k
でソートするキーのフィールド指定、-t
でデリミタの指定をする。
ただし、-k 2
とすると、「2項目目以降で並べ替え」になってしまうため、
項目1つだけ指定して並べ替えたい時は、-k 2,2
のように指定してあげる必要がある。
sort -r -n -k 4,4 -t '\t' popular-names.txt
解答スクリプト
# coding:utf-8 import pandas as pd path = './popular-names.txt' df = pd.read_csv(path, sep='\t', header=None) df.columns = ['Name', 'Sex', 'Count', 'Year'] df_s = df.sort_values('Year', ascending=False) df_s.reset_index(inplace=True, drop=True) print(df_s)
参考記事
19. 各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる
集計系の問題。これも覚えたら超便利。
ポイント
解答コマンド
uniqコマンドの-c
オプションで集計ができる
cut -f 1 popular-names.txt | sort | uniq -c | sort -r
解答スクリプト
# coding:utf-8 import pandas as pd path = './popular-names.txt' df = pd.read_csv(path, sep='\t', header=None) df.columns = ['Name', 'Sex', 'Count', 'Year'] print(df['Name'].value_counts())