【Python】pandasを活用して複数カラムのユニーク値を一括で取り出すプログラム書いてみた

#目次
1. [作成した理由](https://qiita.com/popoporingo/items/94b4d4e155896bf5a1be#%E4%BD%9C%E6%88%90%E3%81%97%E3%81%9F%E7%90%86%E7%94%B1)
1. [本記事の内容](https://qiita.com/popoporingo/items/94b4d4e155896bf5a1be#%E6%9C%AC%E8%A8%98%E4%BA%8B%E3%81%AE%E5%86%85%E5%AE%B9)
1. [使い方](https://qiita.com/popoporingo/items/94b4d4e155896bf5a1be#%E4%BD%BF%E3%81%84%E6%96%B9)
1. [プログラムの解説](https://qiita.com/popoporingo/items/94b4d4e155896bf5a1be#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E8%A7%A3%E8%AA%AC):リクエストあったら書こうかな


#作成した理由
知人に頼まれたのと、面白そうだったから。

#本記事の内容
　データ分析を行なっている方！分析をするとなると、まず最初にデータ俯瞰しません？どんな列があって、どんな直が格納されているか確認しますよね？するよね？？？？
 pythonには大変便利で超絶有能なライブラリpandasってのがあります。これを利用すると
・__列名や行名の取得__が可能です。([参考](https://qiita.com/yuta-38/items/69d03647e19eb29b0730#%EF%BC%93%E8%A6%81%E7%B4%A0%E3%81%AE%E6%8A%BD%E5%87%BA)）
・任意の列に対して、__格納されているデータのユニーク値の確認__ができます。
(これはPandasのほんの一機能にすぎません)
ただし、全ての列に対して格納されているユニークな値を取り出すには一手間加える必要があります。また、分析を行う上で、__列名（要素名）__に加え、格納されている__データ数__、__データ型__、__欠損数（欠損率も）__知れるといいですよね？なので__ユニーク値__に加え上記の太字の奴らを表形式で出すやつ作りました！！長ったらしく書きましたが、、、、

<u>__結論__：作ったpythonプログラム？モジュール？の使い方とプログラムの解説やります。</u>


#使い方
__1.　機能説明__
__2.　[コード直書き（コピペ）して使用](https://qiita.com/popoporingo/items/94b4d4e155896bf5a1be#%E3%82%B3%E3%83%BC%E3%83%89%E7%9B%B4%E6%9B%B8%E3%81%8D%E3%82%B3%E3%83%94%E3%83%9A%E3%81%97%E3%81%A6%E4%BD%BF%E7%94%A8)__
__3.　[モジュールとして使用](https://qiita.com/popoporingo/items/94b4d4e155896bf5a1be#%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%A8%E3%81%97%E3%81%A6%E4%BD%BF%E7%94%A8)__

__🍎りんごの環境は以下の通り__
JupyterLab: 3.0.7
Python: 3.8.6
Pandas: 1.2.2

__ディレクトリ構成__
2.　コード直書き（コピペ）して使用する場合
```任意のrootディレクトリ/
　├ test.csv #機能説明をみてね
　└ Tutorial.ipynb #実行するnotebookです！皆さんは新規で作成してね 
```
3.　モジュールとして使用する場合
```任意のrootディレクトリ/
　├ test.csv #機能説明をみてね
　├ Tutorial.ipynb #実行するnotebookです！皆さんは新規で作成してね
　└ ringo_python_module #りんごが書いたプログラムを格納したファイルだよGitlabからクローンしてね🙃
```

### 機能説明
下記の表１に示すのは、Kaggle（データ分析のコンペサイト）に掲載されているタイタニックチュートリアルのテストデータになります。今回の機能説明はこちらのデータを利用します。（[ダウンロードはこちら](https://www.kaggle.com/c/titanic/data?select=test.csv)）ご賞味あれ。
</n>
<div style="text-align: center;"> 表1:test.csv </div>
![titanic_testdata.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043785/e31e9d28-6fbc-f131-f8e0-148dd77e7ed9.png "表1:テストデータ")
この表１のデータが。。。じゃん！（表２みて欲しいです。）
</n>
<div style="text-align: center;"> 表2:りんごプログラム </div>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043785/1135f54a-f5d5-b48a-7b74-1f4915a73e44.png)
はい。このようにデータの全体像の片鱗を取得できます✧٩(ˊωˋ*)و✧

|| Logical name | Number of data | DataTypes | Missing values | Missing values(%) | Unique value |
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
| __表示内容__ | 要素名 | データ数 | データ型 | 欠損数 | 欠損率| ユニーク値|


## コード直書き(コピペして使用)
[プログラムの解説](https://qiita.com/popoporingo/items/94b4d4e155896bf5a1be#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E8%A7%A3%E8%AA%AC)からコードをコピーしてnotebook(Tutorial.ipynb)にペーストしてください。
コードを実行したら、次は下記のコードを実行していきます。(❁´ω`❁)

```python:Tutorial.ipynb
## 利用するライブラリー
import pandas as pd
import warnings #FutureWarningが表示されるので記述してます。みたい人はこれをコメントアウトして実行してね
warnings.filterwarnings('ignore')

## データの読み込み
df = pd.read_csv("test.csv")

```
できましたか？もしここまででつまづいたら気軽に質問してください(^^;
（エラーによっては答えられないかも、、だけど）

いよいよ表示します！！！下記コードを実行してみてください！！

```python:Tutorial.ipynb
unique_list(df,0) 
```
どうですか？無事に表2と同じ結果が得られたと思いますΣ(ﾟДﾟ)ｽｹﾞｪ!!

## モジュールとして使用
[こちらから](https://gitlab.com/plusdynabook/ringo_python_module)からコードを対象のディレクトリにクローンしてください。
クローンできたら下記を実行してください(/ω＼)

```python:Tutorial.ipynb
import pandas as pd
import warnings
warnings.filterwarnings('ignore')

## クローンしたソースコードを読み込んで実行できるようにします！
from ringo_python_module import count as uq
```

```python:Tutorial.ipynb
## データの読み込み
df = pd.read_csv("test.csv")
```
それでは、いよいよ表示します！！！下記コードを実行してみてください！！

```python:Tutorial.ipynb
uq.unique_list(df,0) 
```
どうですか？無事に表2と同じ結果が得られたと思いますΣ(ﾟДﾟ)ｽｹﾞｪ!!


### 補足
```python:Tutorial.ipynb
unique_list(X,Y) 
```
| 変数|     入る値     | 
| :--- | :-----------: | 
| X    | 読み込んだデータ | 
| Y    | 表示形式:0~3まであるよ |



#プログラムの解説
```python:count.py
def unique_list(x, y):
    colum_dict = {} #空の辞書作成
    a=list(x.columns) #カラムリスト作成
    b=len(x) #ループ回数
    listData=[]
    col=pd.DataFrame(x.columns).T
    T=[y]
    for k in range(len(a)):
        for i, j in enumerate(x):
            colum_dict[i] = j
            
        dz= x[(f"{colum_dict[k]}")].unique()
        listData.append([dz])
        list_df = pd.DataFrame(listData).T
        unique_list = col.append(list_df)
        unique_list = unique_list.T
        unique_list.columns = ('index','Unique value')
        unique_list_Valu=unique_list['Unique value'].astype(str).str.replace('[', '').str.replace(']', '')
        unique_list_Index=unique_list['index']
        unique_list = pd.concat([unique_list_Index,unique_list_Valu], axis=1)

    df = pd.concat([
    x.count().rename('Number of data'),
    x.dtypes.rename("DataTypes"),
    x.isnull().sum().rename("Missing values"),
    (x.isnull().sum() * 100 / x.shape[0]).rename("Missing values (%)").round(2),
    ], axis=1)
    df_a = df.reset_index()
    info = pd.merge(df_a, unique_list).rename(columns={'index': 'Index'})
    if y==0 :
        info = info.rename(columns={'Index': 'Logical name'})
        return info
    elif y==1:
        info2=info.rename(columns={'Index':''}).set_index('')
        return info2
    elif y==2:
        info2=info.rename(columns={'Index':''}).set_index('')
        return df
    elif y==3:
        list_df = unique_list_Valu.T.reset_index()
        list_da1 = list_df['Unique value'].\
                           str.replace('^\x20+', '').\
                           str.replace(" {2,}", " ").\
                           sort_values().\
                           str.split(' ', expand=True)
        list_da2 = list_df['Unique value']
        list_da1=pd.concat([unique_list_Index,list_da1], axis=1)
        return list_da1
    else :
        return df_a
```