【お蔵入り中】未知のpandas.DataFrameの中身をサクッと確認する

未知のpandas.DataFrameの中身をサクッと確認したいときに使える関数をつくったので記事にします｡
この関数を使えばデータに含まれる要素を登場回数が多い順に表示することができます｡

コード全文は記事末尾にまとめて掲載しています｡(コピペ用)

# ※2022-03-29時点追記
コメント欄で`df['登場人物'].value_counts()`を使うとよいのでは？ というコメントをいただきました。
たしかに…！ となったのであとで記事編集いたします。

以下の記事の内容でやっていることは`df['登場人物'].value_counts()`でほぼカバーできます。
メリットを挙げるなら順位表示と件数表示を同時にできることかなと思います。

せっかくなので割合・積み上げ割合とかを表示できるようにすると新規性があるかも…？
時間があれば追記したいと思います。


## 本記事の想定読者
- Pythonユーザー
- pandasのDataFrameを使う
- 読み込んだデータの中身をサクッと確認したい

## 関数の使用例
ランダムに生成された架空のデータを使って実際の使用例を示します｡
今回紹介する`icount()`関数の詳細はのちほど説明します｡

なお､結果はランダムに生成されたものであり出典の作品とは一切関係しません｡[^1]

[^1]:登場人物名の出典は [タコピーの原罪](https://shonenjumpplus.com/episode/3269754496638370192) です｡
ステマがしたかっただけです｡興味のある方は読んでみてください｡

```Python:コードの実行例
import pandas as pd

df = pd.read_csv('original_sin.csv')

icount(df['登場人物'])
```

```:コードの実行結果
全5件中5件表示
1. タコピー 27件
2. じゅんや 24件
3. まりな 20件
4. しずか 19件
5. なおき 10件
```

これでデータにどのような要素が含まれるか(あるいは含まれないか)がわかりました｡

## icount()の中身
例で用いた`icount()`の中身は以下のとおりです｡[^3]

[^3]:`icount()`のiは`iterable`のiのつもりです｡
実際にpandas.DataSeries以外のiterableなクラス(listなど)でも使えます｡

```Python:icount()の中身
from collections import Counter

def icount(iterable, topK=10):
    """iterableな要素を受け取って要素の多い順に表示する"""
    c = Counter(iterable)
    mc = c.most_common()
    topK = len(mc) if topK > len(mc) else topK
    print(f'全{len(mc)}件中{topK}件表示')
    for i in range(topK):
        print(f'{i+1}. {mc[i][0]} {mc[i][1]}件')
```

関数内部で`Counter.most_common()`を利用しています｡

`icount()`の役割は`Counter.most_common()`の利用の簡易化です｡
加えて`topK`を引数にとって上位何件まで表示するかを指定することができます｡

## 実際の使用イメージ
未知のデータを読み込んだ際にその中身をおおまかに把握したいケースを考えます｡
- データにどんな要素が含まれるのかを知りたい
- データに**想定外の要素が含まれていないか**を確認したい

今回は`original_sin.csv`というCSVファイルを読み込みます｡[^2]
[^2]:「タコピーの原罪」の英語タイトル「Takopi's Original Sin」を元にしています｡

```Python:df.info()の実行例
import pandas as pd

df = pd.read_csv('original_sin.csv')
```

この時点ではこのCSVデータにどのような要素が含まれているかまだわかりません｡

まず`df.info()`でデータの概要を把握します｡

```Python:df.info()
df.info()
```

```:df.info()の結果
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100 entries, 0 to 99
Data columns (total 3 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   日付      100 non-null    object
 1   時刻      100 non-null    object
 2   登場人物    100 non-null    object
dtypes: object(3)
memory usage: 2.5+ KB
```

[日付],[時刻],[登場人物]という列があることがわかりました｡

次に`df.head()`でデータの雰囲気をつかみます｡

```Python:df.head()
df.head()
```

```:df.head()の結果
	日付	時刻	登場人物
0	2022-07-17	15:53:56	なおき
1	2022-01-21	11:21:24	じゅんや
2	2022-09-06	12:41:08	まりな
3	2022-09-02	12:15:32	じゅんや
4	2022-04-22	13:35:37	しずか
```

データのざっくりとした雰囲気はつかめました｡

しかし[登場人物]にどのキャラが含まれているか(あるいは含まれないか)､
どのキャラの登場頻度が高いかなどについてはまだ情報がありません｡

この[登場人物]の列にどういう要素が含まれているかを調べるために
`icount()`を使います｡


```Python:icount()の実行
from collections import Counter

def icount(iterable, topK=10):
    """iterableな要素を受け取って要素の多い順に表示する"""
    c = Counter(iterable)
    mc = c.most_common()
    topK = len(mc) if topK > len(mc) else topK
    print(f'全{len(mc)}件中{topK}件表示')
    for i in range(topK):
        print(f'{i+1}. {mc[i][0]} {mc[i][1]}件')

icount(df['登場人物'])
```

```:コードの実行結果
全5件中5件表示
1. タコピー 27件
2. じゅんや 24件
3. まりな 20件
4. しずか 19件
5. なおき 10件
```

これで[登場人物]には5人(？)のキャラクターがいて､
それぞれが何回ずつ登場するかがわかりました｡

同時に､この5人以外のキャラが**含まれていないこと**もわかりました｡[^5]
もしデータに想定外のデータが混ざっていた場合でも､この段階で気付くことができます｡
[^5]:チャッピーも入れたらよかったと後になって思いました｡


### 留意事項
`icount()`だけでは登場頻度が低い要素について見落とす可能性があります｡

一方で､無効な値が大量に含まれている場合にすぐに察知できるなどの利点もあるので､
標題のとおりデータを**サクッと確認する**用途に向いてると思います｡


## まとめ
- 未知のデータを扱う際に､データの中身をサクッと確認できるようになった！

## 関連記事

今回の例で使用したランダムな架空のデータは以下の記事の関数を使って作成しました｡
データ分析でテスト用データをサクッとつくりたいときにご利用ください｡

https://qiita.com/mochi_gu_ma/items/eb715c047312ddfa7626

## コード全文
<details><summary>コード全文(クリックで表示)</summary>

```Python:コード全文
from collections import Counter

import pandas as pd

def icount(iterable, topK=10):
    """iterableな要素を受け取って要素の多い順に表示する"""
    c = Counter(iterable)
    mc = c.most_common()
    topK = len(mc) if topK > len(mc) else topK
    print(f'全{len(mc)}件中{topK}件表示')
    for i in range(topK):
        print(f'{i+1}. {mc[i][0]} {mc[i][1]}件')

```

</details>