データクレンジング2　DataFrameを用いたデータクレンジング

[Aidemy](https://aidemy.net/)　2020/9/30
#　はじめに
　こんにちは、んがょぺです！バリバリの文系ですが、AIの可能性に興味を持ったのがきっかけで、AI特化型スクール「Aidemy」に通い、勉強しています。ここで得られた知識を皆さんと共有したいと思い、Qiitaでまとめています。前回が初投稿でしたが、多くの方に読んでいただけてとても嬉しいです。ありがとうございます！
　今回は、データクレンジングの２つ目の投稿になります。どうぞよろしくお願いします。


＊本記事は「Aidemy」での学習内容を「自分の言葉で」まとめたものになります。表現の間違いや勘違いを含む可能性があります。ご了承ください。

今回学ぶこと
・CSVについて
・欠損値（NaN）に対する処理
・辞書でキーごとにデータを処理する

#1　CSV
##PandasでCSVを読み込む
・CSVとは、データ分析でよく使われるデータファイルのこと。まずはPandasを使って読み込む。
__・pd.read_csv("データのファイル名",header=ヘッダーとなる列の指定)__
＊headerの指定が特にない時はNone

```python
import pandas as pd
# wine.csvの読み込み
df = pd.read_csv("./4050_data_cleansing_data/wine.csv", header=None)
# カラムの名前を設定
df.columns = [省略]
#　出力
df
```

##CSVライブラリでCSVの作成
・Pythonに内蔵されている「CSVライブラリ」を使ってCSVを作成する。
__・with open("ファイル名","w") as csvfile：__　とし、その中で
__writer=csv.writer(csvfile, lineterminator="\n")__
(csvfileと改行コードを引数とするwriterメソッド)を作成し、これを用いて
__writer.writerow([データ])__　でデータを入力する。

```python
import csv
with open("ファイル名","w") as csvfile:
  writer=csv.writer(csvfile, lineterminator="\n")
  writer.writerow(["version","year","gen"]) #1行目はカラム名
  writer.writerow(["赤緑",1996,1])
  writer.writerow(["金銀",1999,2])
  writer.writerow(["RS",2002,3])

#読み込み
with open("ファイル名","r") as csvfile:
  print(csvfile.read())
# version,year,gen
# 赤緑,1996,1
# 金銀,1999,2
# RS,2003,3
```

##PandasでCSVの作成
・DataFrameをCSVにする時はこちらの方が簡単
__・DataFrameのデータ.to_csv("ファイル名")__

```python
data={"version":["赤緑","金銀","RS"],"year":[1996,1999,2002],"gen":[1,2,3]}
df=pd.DataFrame(data)
df.to_csv("ファイル名")
```

#2 欠損値（NaN）に対する処理
##NaNを含む行や列の削除
・NaNを含む行や列の削除のことを__「リストワイズ削除」__という。リストワイズ削除はdropna()関数で行う。引数を指定しなければ行が、axis=1に指定すれば列が削除される。
__・DataFrameのデータ.dropna()__

・リストワイズ削除を使うとデータ数が少なくなりすぎる場合は、欠損の少ない列を残し、そこからNaNを含む行を削除すると良い。これを__「ペアワイズ削除」__という。
__・DataFrameのデータ[[残す列]].dropna()__

```python
data={"version":["赤緑","金銀","RS"],"year":[1996,1999],"gen":[1]}
df=pd.DataFrame(data)
# リストワイズ削除だとデータが少ないので、version,year列だけ残して、NaNを含む行を削除
df[[0,1]].dropna()
#version year
#赤緑 1996
#金銀 1999
```

##欠損値の補完（1）
・削除ではなく代替データの代入で補完する。fillna()関数を使う。引数には「代替データ」または「method="ffill"」（前行の値を適用する）を設定する。
__・DataFrameのデータ.fillna()__

```python
data={"version":["赤緑","金銀","RS"],"year":[1996,1999],"gen":[1]}
df=pd.DataFrame(data)
# NaNを前のデータで置き換え
df.fillna(method="ffill")
#version year gen
#赤緑 1996 1
#金銀 1999 1
#RS  1999 1
```

##欠損値の補完（2）
・fillna()の引数にmean()関数を使うことで、代替データを「その列の平均値」で置き換えられる。
__・DataFrameのデータ.fillna(DataFrameのデータ.mean())__

```python
data={"version":["赤緑","金銀","RS"],"year":[1996,1999],"gen":[1]}
df=pd.DataFrame(data)
# NaNを前のデータで置き換え
df.fillna(method="ffill")
#version year gen
#赤緑 1996 1
#金銀 1999 1
#RS  1997.5 1
```

#3 辞書でキーごとにデータを処理する
##キーごとに計算する
・辞書やCSV（DataFrame）のキーごとの平均値や最大値などを、mean()やmax()などの統計関数を使って算出できる。
__・辞書やdf[キー].統計関数__

```python
df = pd.read_csv("./4050_data_cleansing_data/wine.csv", header=None)
df.columns = ["","Alcohol",(省略)]
#　"Alcohol"の平均値算出
df["Alcohol"].mean()
# 13.000617977528091
```

##重複データの抽出、削除
・全く同じデータの抽出はduplicated()メソッドを使う。削除はdrop_duplicates()メソッドを使う。
__・重複のあるデータ.duplicated()__
__・重複のあるデータ.drop_duplicates()__

```python
data={"version":["赤緑","金銀","RS","赤緑"],"year":[1996,1999,2002,1996],"gen":[1,2,3,1]}
df=pd.DataFrame(data)
#　重複データの削除
df.drop_duplicates()
# version,year,gen
# 赤緑,1996,1
# 金銀,1999,2
# RS,2003,3
```

##すでにあるキーに対応する新しいキーを作る
・すでにあるキーに対応する新しいキーを作ることを__「マッピング」__という。
__・DataFrameのデータ[新キー] = DataFrameのデータ[参照元のキー].map(辞書型の対応表)__

```python
data={"version":["赤緑","金銀","RS"],"year":[1996,1999,2002],"gen":[1,2,3]}
df=pd.DataFrame(data)
# 辞書型の対応表を作成してからマッピング
version_map={"赤緑":"Kanto","金銀":"Johto","RS":"Hoenn"}
df["region"] = df["version"].map(version_map)
df
# version,year,gen,region
# 赤緑,1996,1,Kanto
# 金銀,1999,2,Johto
# RS,2003,3,Hoenn
```

##数値データの範囲を設定してカテゴリ分け
・「０〜5」「６〜10」のように範囲を設定して、範囲ごとにデータを分けたり集計したりする。このような処理のことを「ビン分割」という。ビン分割はpd.cut()で行う。
__・pd.cut(データ[範囲を指定するキー], [範囲のリスト], labels=[範囲ごとの名前のリスト])__　#ビン分割
・分割数を指定し、自動で範囲を振り分けてくれる方法もある
__・pd.cut(データ[範囲を指定するキー], 分割数)__
__・pd.value_counts(ビン分割したデータ)__#分割した範囲ごとのデータ数の集計

```python
data={"version":["赤緑","金銀","RS","DP"],"year":[1996,1999,2002,2006],"gen":[1,2,3,4]}
df=pd.DataFrame(data)
# yearで範囲指定、先に範囲のリストを作成する。
range = [1996,2000,2007]
range_name = ["1996-2000","2000-2007"]
cut_df = pd.cut(df["year"], range, labels=range_name)
pd.value_counts(cut_df)
#1996-2000  2
#2000-2007  2
```

#まとめ
・データ分析ではCSVというデータファイルがよく使われる。CSVはpython標準のライブラリかPandasを使って作成される。
・欠損値はdropna()で削除したり、fillna()で補完したりして処理する。
・辞書やDataFlameではキーを参照してvalueの計算をしたり、重複データを削除したり（drop_duplicates）、新キーを作ったり(map)、範囲を指定して分割したり(pd.cut)できる。

以上です。ここまで読んでくださり、ありがとうございます。