言語処理100本ノック 2020をやった 第2章

# はじめに
満を持して[言語処理100本ノック 2020](https://nlp100.github.io/ja/)が公開されたので早速やってみます。1章は2015と全く同じようなので（しかもちょうどそこだけはやっていたので）、2章からやっていきます。

いくつかQiitaにも既に記事は上がっていますが、自然言語処理の概観が学べる上に、序盤は言語処理に限らずLinux初心者や竸プロ初心者にも役に立つと思います。

# 第2章: UNIXコマンド
popular-names.txtは，アメリカで生まれた赤ちゃんの「名前」「性別」「人数」「年」をタブ区切り形式で格納したファイルである．以下の処理を行うプログラムを作成し，popular-names.txtを入力ファイルとして実行せよ．さらに，同様の処理をUNIXコマンドでも実行し，プログラムの実行結果を確認せよ．

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

```python:コード
import pandas as pd

df = pd.read_csv('popular-names.txt', delimiter='\t', header=None)
print(len(df.index))
```

```:コマンド
wc -l popular-names.txt
```

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

```python:コード
import pandas as pd

df = pd.read_csv('popular-names.txt', delimiter='\t', header=None)
df.to_csv('popular-names-space.txt', sep=' ', index=False, header=None)
```

```:コマンド
sed -e $'s/\t/ /g' popular-names.txt > popular-names-space.txt
```
※正規表現の部分はMac（BSD）用です。Linuxでは動作しないかと思います。

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

```python:コード
import pandas as pd

df = pd.read_csv('popular-names.txt', delimiter='\t', header=None)
df[0].to_csv('col1.txt', index=False, header=None)
df[1].to_csv('col2.txt', index=False, header=None)
```

```:コマンド
cut -f 1 popular-names.txt > col1.txt
cut -f 2 popular-names.txt > col2.txt
```

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

```python:コード
import pandas as pd

df1 = pd.read_csv('col1.txt', header=None)
df2 = pd.read_csv('col2.txt', header=None)
df_concat = pd.concat([df1, df2], axis=1)
df_concat.to_csv('col3.txt', sep='\t', index=False, header=None)
```

```:コマンド
paste col1.txt col2.txt > col3.txt
```

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

```python:コード
import pandas as pd
n = int(input())

df = pd.read_csv('popular-names.txt', delimiter='\t', header=None)
print(df.head(n))
```

```:コマンド
head -5 popular-names.txt
```

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

```python:コード
import pandas as pd
n = int(input())

df = pd.read_csv('popular-names.txt', delimiter='\t', header=None)
print(df.tail(n))
```

```:コマンド
tail -5 popular-names.txt
```

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

```python:コード
import pandas as pd
n = int(input())

df = pd.read_csv('popular-names.txt', delimiter='\t', header=None)

for i in range(1, len(df) // n + 1):
    df[n*i:n*i+n:].to_csv('popular-names' + str(i) + '.txt', index=False, header=None)
```
ここはあまり美しくないですが、DataFrameを行ごとに分割する簡潔な書き方がなさそうだったので。

```:コマンド
split -l 200 popular-names.txt popular-names-
```

## 17. １列目の文字列の異なり
1列目の文字列の種類（異なる文字列の集合）を求めよ．確認にはcut, sort, uniqコマンドを用いよ．

```python:コード
import pandas as pd

df = pd.read_csv('popular-names.txt', delimiter='\t', header=None)
print(set(list(df[0])))
```

```:コマンド
cut -f 1 popular-names.txt | sort | uniq
```
`uniq`は事前にソートが必要。

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

```python:コード
import pandas as pd

df = pd.read_csv('popular-names.txt', delimiter='\t', header=None)
print(df.sort_values(2, ascending=False))
```

```:コマンド
sort -n -r -k 3 popular-names.txt | head -10
```
※出力が長くなってしまうため`head -10`で10行に絞っています

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

```python:コード
import pandas as pd

df = pd.read_csv('popular-names.txt', delimiter='\t', header=None)
print(df[0].value_counts())
```

```:コマンド
cut -f 1 popular-names.txt | sort | uniq -c | sort -n -r -k 1 | head -10
```
※出力が長くなってしまうため`head -10`で10行に絞っています

# おわりに
2章で学べること

* pandas.DataFrameの基礎
* Unixコマンドでの文字列・ファイル操作
    * sed
    * cut
    * paste
    * head
    * tail
    * split
    * sort
    * uniq