Python初心者が言語処理100本ノックで苦戦を強いられている~pandasの関数たち~


最近、なんかやろうということで言語処理の勉強をし始めました。

そんな中で、[こちら](https://nlp100.github.io/ja/)の「言語処理100本ノック2020」をPythonを使ってやっていましたら、第２章のUnixコマンドが結構難しくて（自分だけかもしれない。。。）苦戦したので、この章で扱った関数だけでも知っておこうということで色々調べてまとめることにしました。

もし自分と同じく、苦戦している人の助けになれば幸いです。

## 環境
Python 3.7.0
pandas 1.0.3

## csv/tsvファイルを読み込む`read_table()`
例えば、以下のようなファイルを読み込もうと思った時は

```text:text.txt
ジョン	M	5441	1881
太郎	M	4664	1881
花子	M	4636	1881
```

下のようにして読み込むことができる。

```py:read_table.py
import pandas as pd 

df = pd.read_table('test.txt', header=None)
print(df)
```

ちなみに、出力結果は

```
     0  1     2     3
0  ジョン  M  5441  1881
1   太郎  M  4664  1881
2   花子  M  4636  1881
```

となる。
`read_table()`でファイルから読み込んだ結果をprintしているだけの簡単なもの。
`read_table()`はデフォルトとして区切り文字がタブ`\t`になっているので、もし別のものを区切り文字にしようと思ったときは`read_table(sep=',')`という風にするとできる。

また、引数の`header=None`は見出し行がないことを指定している。デフォルトでは1行目が見出しとして認識される。
なので、もし見出しがない場合などは`None`を指定する。そのときは上のように0から始まる連番が列名として割り振られる。


## csvとして書き出す`to_csv()`

今度はデータをcsvファイルとして出力しようと思った時に使う関数。
例えば上の`test.txt`の区切り文字をカンマにして別ファイルに出力しようと思った時

```py:to_csv.py
import pandas as pd

df = pd.read_table('test.txt', header=None)
df.to_csv('test_o.txt', sep=',', index=False, header=None)
```

という風にするとできる。
上から順に、`read_table()`でファイルを読み込み、読み込んだデータを新たなファイル`test_o.txt`ファイルに出力。その時の区切り文字はカンマで、見出し列と見出し行はなし。

```text:test_o.txt
ジョン,M,5441,1881
太郎,M,4664,1881
花子,M,4636,1881
```

ちなみに`index`と`header`をどちらも`True`にすると以下のような出力結果になる

```text:test_o2.txt
,0,1,2,3
0,ジョン,M,5441,1881
1,太郎,M,4664,1881
2,花子,M,4636,1881
```

このようにして、見出しの行と列が追加された状態で出力される。

## 複数のオブジェクトを連結させる`concat()`
複数のデータを結合させたい時に使う関数。
例えば新たに`test_1.txt`というファイルを作成

```text:test_1.txt
カナ	F	5438	1881
タケル	M	4774	1881
リョウ	M	5536	1881
```

この`test_1.txt`と先ほどの`test.txt`を一緒のファイルにまとめたい思った時、以下のようにすることができる

```py:concat.py
import pandas as pd 

df1 = pd.read_table('test.txt', header=None)
df2 = pd.read_table('test_1.txt', header=None)

df_concat = pd.concat([df1, df2])
print(df_concat)
```

やっていることは、二つのファイルを読み込んで、それらを`concat()`を使って結合。その後、printで出力。

このとき、結合するデータは2つ以上でも可能。そのときは`[df1, df2, df3]`という風に引数に加えてやるとできる。

結果は、

```terminal
     0  1     2     3
0  ジョン  M  5441  1881
1   太郎  M  4664  1881
2   花子  M  4636  1881
0   カナ  F  5438  1881
1  タケル  M  4774  1881
2  リョウ  M  5536  1881
```

という風に結合されて出力される。

また、`concat()`の引数の`axis`を指定することで結合する向きを変えられることができる。

```py:concat2.py
import pandas as pd 

df1 = pd.read_table('test.txt', header=None)
df2 = pd.read_table('test_1.txt', header=None)

df_concat = pd.concat([df1, df2], axis=1)
print(df_concat)
```

結果

```terminal
     0  1     2     3    0  1     2     3
0  ジョン  M  5441  1881   カナ  F  5438  1881
1   太郎  M  4664  1881  タケル  M  4774  1881
2   花子  M  4636  1881  リョウ  M  5536  1881
```

このように`axis=1`と指定することで横向きに結合することもできる。


## 先頭or末尾の行を返す`head()`, `tail()`
読み込んだデータの先頭、または末尾を出力したい時に使える関数。

```py:head_tail.py
import pandas as pd

df = pd.read_table('test.txt', header=None)
print(df.head(2)) # デフォルトで先頭から5行だけ取得してくくる
print('===========================')
print(df.tail(2)) # 同じくデフォルトで末尾から5行だけ取得
```

結果

```terminal
     0  1     2     3
0  ジョン  M  5441  1881
1   太郎  M  4664  1881
===========================
    0  1     2     3
1  太郎  M  4664  1881
2  花子  M  4636  1881
```

このように、`head(n)`、`tail(n)`とするとこでデータの先頭もしくは、末尾から`n`行だけ出力する。
何も指定しなかったときは、デフォルトで5行だけ出力されるる

## 特定の位置を取得する`loc`

データの特定の位置の単独もしくは、複数の要素を選択、取得、変更などをしたい時に使える。
例えば、`test.txt`で太郎の3項目目を変更するときは

```py:loc.py
import pandas as pd 

df = pd.read_table('test.txt', header=None)
print(df)
print('=========================')
df.loc[1, 2] = 5000
print(df)
```

結果は

```
     0  1     2     3
0  ジョン  M  5441  1881
1   太郎  M  4664  1881
2   花子  M  4636  1881
=========================
     0  1     2     3
0  ジョン  M  5441  1881
1   太郎  M  5000  1881
2   花子  M  4636  1881
```

という風に1行目の2列目の値が更新されているのが確認できる。

また、データから複数行選びたい場合は、スライスと同じように`[start:stop:step]`で指定できる

```py:loc1.py
import pandas as pd 

df = pd.read_table('test.txt', header=None)
print(df.loc[:1])
```

結果

```
     0  1     2     3
0  ジョン  M  5441  1881
1   太郎  M  4664  1881
```

また、特定の項目だけを選択することもできる。
例えば、1~2行目の名前と性別だけを取得しようとした場合

```py:loc2.py
import pandas as pd 

df = pd.read_table('test.txt', header=None)
print(df.loc[:1, [0, 1]])
```

という風にすると

```
     0  1
0  ジョン  M
1   太郎  M
```

ちゃんと1~2行目の名前と性別だけが出力された結果を得ることができる

## ユニークな値を出力する`unique()`
例えば、名前が重複している以下のファイルから、重複を弾いたユニークな名前を得たいと思ったときは

```text:test_2.txt
ジョン	M	5441	1881
太郎	M	4664	1881
花子	F	4636	1881
太郎	M	4333	1881
花子	F	5000	1881
```

```py:unique.py
import pandas as pd 

df = pd.read_table('test_2.txt', header=None)
print(df[0].unique())
```

と書くと、重複しないユニークな値の配列が出力される。

```
['ジョン' '太郎' '花子']
```

`df[0]`の部分でデータの１列目（＝名前の列）を指定し、そのユニークな値を取得するようにしている。

## 要素を基準にソートする`sort_values()`

ファイルのある項目などでソートしようと思った時に使える関数。

以下のファイルの3項目目でソートしようと思った時

```test.txt
ジョン	M	5441	1881
太郎	M	4664	1881
花子	F	4636	1881
太郎	M	4333	1881
花子	F	5000	1881
```

```py:sort_values.py
import pandas as pd 

df = pd.read_table('test.txt', header=None)
print(df.sort_values(2))
```

結果

```
     0  1     2     3
3   太郎  M  4333  1881
2   花子  F  4636  1881
1   太郎  M  4664  1881
4   花子  F  5000  1881
0  ジョン  M  5441  1881
```

という風に3項目目(割り振られた値では2)の数値でソートされている。
ソートを降順にしたいと思ったときは、`sort_values(2, ascending=False)`としていすれば降順で出力される。

また、ソートによってズレたインデックスを直したいと思ったときは`reset_index()`という関数を使う。

```py:sort_values.py
import pandas as pd 

df = pd.read_table('test.txt', header=None)
print(df.sort_values(2).reset_index(drop=True))
```

```
     0  1     2     3
0   太郎  M  4333  1881
1   花子  F  4636  1881
2   太郎  M  4664  1881
3   花子  F  5000  1881
4  ジョン  M  5441  1881
```

`reset_index()`の部分でインデックスをリセットしている。また引数の`drop=True`で元のインデックスを削除している。

## ユニークな値とその出現回数を出力する`value_counts()`

ファイルの中のある項目で要素の出現回数(重複した数)でソートしようと思った時に使う関数。

```text:test.txt
ジョン	M	5441	1881
太郎	M	4664	1881
花子	F	4636	1881
太郎	M	4333	1881
花子	F	5000	1881
```

このファイルで名前の出現回数順にソートしようと思った時

```py:value_counts.py
import pandas as pd 

df = pd.read_table('test.txt', header=None)
print(df[0].value_counts())
```

と書くことができ、結果は以下のようになる。

```
太郎     2
花子     2
ジョン    1
Name: 0, dtype: int64
```

`df[0]`で項目を指定し、`value_counts()`で項目の要素の出現回数を出力している

また、`sort_values()`と同じように引数に`ascending=True`とすることで昇順にソートし直すことができる。
さらに、ソートをせずに出力したい場合は引数に`sort=False`とするとソートせずに出力される。

## まとめ
これまで紹介してきた通り、pythonを使って色々ファイル操作をしたり、データを整形したり、別ファイルに出力したりなんてことができるらしいです。
今までモバイルアプリ系のことしかやってこなかったので、全然知りませんでした。

100本ノックさん曰く、ここはまだ序盤も序盤らしいので気を引き締めてここからの章も頑張っていきます