【DataFrameの前処理】欠損値とデータ型の確認、特定の列の削除、データの要約

## はじめに
csvファイルから読み込んだデータに対して、以下の前処理を行ったのでご紹介いたします。

- **欠損値の確認**
- **データ型の確認**
- **特定の値の削除**
- **データの要約（統計量の表示、相関行列の表示）**

※機械学習やプログラミング関係の内容を他にも投稿していますので、よろしければ[こちら](https://qiita.com/oki_kosuke/items/34b1071224953776c211#%E6%8A%95%E7%A8%BF%E4%B8%80%E8%A6%A7)の一覧から他の投稿も見て頂けますと幸いです。

### 環境

- conda 4.8.3
- python 3.8.3
- pandas 1.0.5

## データの前処理
データは[こちら](https://github.com/okikosuke/sample/tree/main/sample_data)に保存しているdata.csvを使用します。

### データの読み込み
データを読み込みます。data.csvのファイルは実行中のディレクトリに保存する必要があります。

```python
# ライブラリのインポート
import pandas as pd
# データの読み込み
df_raw = pd.read_csv("data.csv", encoding="shift_jis")
```

- encodingで文字コードを指定（excelをcsv変換した場合にはshift_jisになっている）

読み込んだデータを表示します。

```python
# head()の()に数値を指定して先頭から表示する行数を指定、記入しない場合はデフォルトの5で表示される
df_raw.head()
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1057114/8ccaa1e6-8dbe-f6f2-f2c9-6dba6a5659a0.png" width="100%">

読み込んだデータの大きさを表示します。

```python
df_raw.shape
```
```:出力結果
(750, 11)
```
データの個数（行数）は750、列数は11です。

### 欠損値の確認
欠損値を確認していきます。

```python
df_raw.isnull().any()
```

- データフレーム.isnull()で欠損値の確認を行います（True：欠損値あり、Flase：欠損値なし）
- isnull().any()で列中に一つでも欠損値があるか確認（True：1つ以上欠損値あり、Flase：欠損値なし）
- isnull().all()で列中の全てが欠損値であるか確認（True：全て欠損値、Flase：欠損値がある）


```:出力結果
No.    False
x1     False
x2     False
x3     False
x4     False
x5     False
x6     False
x7     False
x8     False
x9     False
y      False
dtype: bool
```

今回のデータフレームは全ての列で欠損値がないことが分かります。



### データの型の確認

```python
df_raw.dtypes
```
```:出力結果
No.      int64
x1     float64
x2     float64
x3     float64
x4     float64
x5     float64
x6     float64
x7     float64
x8     float64
x9     float64
y       object
dtype: object
```

y列はobjectであり、数値以外の値が混ざっていることが分かります。

- int：整数型
- float：小数型
- object：オブジェクト型

y列の詳細について見ていきます。

```python
df_raw["y"].value_counts(ascending=True)
```
```:出力結果
71.1814     1
273.815     1
117.735     1
163.896     1
112.387     1
           ..
231.853     1
159.988     1
236.276     1
200.473     2
NG         43
Name: y, Length: 707, dtype: int64
```

y列には43個のNGという文字列データが含まれていることが分かります。（データ型がobjectのデータ（行）のみ抽出するコードがあればそちらの方が適切かもしれません。また調べてみます） 

### 特定の列の削除
y列からNGを取り除いていきます。

```python
# yが"NG"の列を削除したデータフレームを新たに作る（drop=Trueで新たにindex列を振り直すことができる）
df_raw_new = df_raw[df_raw["y"] != "NG"].reset_index(drop=True)
df_raw_new.head()
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1057114/26f02a60-6c0c-1acf-3eca-3478ad07db8d.png" width="100%">


新しいデータの大きさを表示します。

```python
df_raw_new.shape
```
```:出力結果
(707, 11)
```

データの個数（行数）は707で、当初の750からNGの43個のデータが無事に取り除かれていることが分かります。

データの型の確認をしておきます。

```python
df_raw.dtypes
```
```:出力結果
No.      int64
x1     float64
x2     float64
x3     float64
x4     float64
x5     float64
x6     float64
x7     float64
x8     float64
x9     float64
y       object
dtype: object
```

y列はNGを取り除いてもデータの型は変わりませんでした。（ここは疑問なのでまた調べたいです）


のちの分析のことを考えてこの段階でNo.の列を削除しておきます。

```python
df = df_raw_new.drop("No." , axis=1)  # axis=1で横方向を指定
df.head()
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1057114/d9c80c24-f0bf-9223-7eb0-4f35f8736f91.png" width="100%">

### データの要約
作成したデータフレームの要約をしていきます。 まずは統計量を表示させます。

```python
df.describe()
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1057114/97034fdf-8a5f-5b5a-92ac-88794468ba41.png" width="100%">

各列の統計量が一目で分かり非常に便利です。（この段階でy列が除外されていますが、上でデータ型を確認した際にy列はobject型と認識されていることに起因していると考えます）

相関係数を計算し、ヒートマップとして表示します。このようなデータの図示についてはまた改めてまとめようと思います。

```python
import matplotlib.pyplot as plt
import seaborn as sns

# 相関行列の計算
correlation_coefficients = df.corr()

# 以下で相関行列のヒートマップ (相関係数の値あり) を描画
plt.rcParams['font.size'] = 12
plt.figure(figsize=(20, 12)) 
sns.heatmap(correlation_coefficients, vmax=1, vmin=-1, cmap='seismic', square=True, annot=True, xticklabels=1, yticklabels=1)
plt.show()
```

![heatmap_corr_coef.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1057114/de8d8b09-ff44-9082-e79b-407d1b3290ad.png)

変数間（x1～x9）に相関はほぼ見られないという結果です。

### データの保存

ここまでの前処理を施したデータをcsvファイルとして保存します。前処理したデータを使用する際はこのcsvファイルを読み込んで使っていきたいと思います。データは[こちら](https://github.com/okikosuke/sample/tree/main/sample_data)にdf.csvとして保存しています。

```python
df.to_csv("df.csv", encoding="shift_jis", index=False)
```

- indexはindex化したデータを残すかどうか設定（True：列として残さない、False：残す）

## 最後に
csvファイルから読み込んだデータに対して、様々な前処理を行ったのでご紹介しました。前処理の手法はまだまだ沢山あるのでまたご紹介していきたいと思います。
### 参考

- [note.nkmk.me](https://note.nkmk.me/python-pandas-nan-judge-count/)
- [化学のための Pythonによるデータ解析・機械学習入門](https://www.amazon.co.jp/%E5%8C%96%E5%AD%A6%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE-Python%E3%81%AB%E3%82%88%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E8%A7%A3%E6%9E%90%E3%83%BB%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E5%85%A5%E9%96%80-%E9%87%91%E5%AD%90-%E5%BC%98%E6%98%8C/dp/4274224414)