機械学習における前処理2　データの取得

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

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

今回学ぶこと
・Excelからのデータ取得
・データベースからのデータ取得

#Excelからのデータ取得
##データ読み込み
・データ前処理の一番最初に行うことは__「データの読み込み」__である。
・データの読み込み元であるデータソースには__「ファイル」「データベース」「Webサイト」__などがあり、今回はその中でも読み込むことが多い__Excelファイルとデータベースからのデータ取得__について扱う。

・Excelからのデータ読み込みは__pandas__で行う。
・「データハンドリング2」で学んだように、Excelファイルの読み込みには__pd.read_excel()__を使う。
・この引数には「ファイルのリンク」と「Excel内のシート名」を指定できる。
・また、第一引数には個別に設定した__pd.ExcelFile("ファイル名")__を渡すこともできる。

##Excelデータの結合
・__複数のシートに整理されているデータを一つのデータとして扱いたい時__は、前処理として、__データの結合__を行う必要がある。
・例としては、商品データのシートAと販売データのシートBを横方向に結合させるといったことが考えられる。
・この結合には__pd.merge(left,right,on=)__を使う。
・引数「left」「right」は左側/右側に結合するシートの指定、「on」は結合に使う列の名前を指定する。

・コード![スクリーンショット 2020-10-29 14.43.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/e487d03e-75a2-0ef9-8df3-f855081f1d55.png)

・結果![スクリーンショット 2020-10-29 14.43.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/963997fe-836e-c819-f87a-563a13a7143a.png)

##Excelデータの絞り込み
・読み込んだり結合したりしたExcelデータ（シート）から、特定の文字列を持つデータ（行）を絞り込みたい時は、__DataFlame.query('指定する文字列のある列 > 文字列')__とする。
・この文字列について、複数指定したい時はリストで渡し、上記コードの「>」の部分は「==」または「in」にする。

・例えば、pandasで読み込んだデータ「df」のproduct_idが1と3の行を抽出したい時は以下のようにする。

```python
df.query('product_id == [1,3]')
```

##データの集約（グループ化）
・読み込んだ商品シート「df」に「type」という列があり、そこではデータが、食品を表す「food」、飲料を表す「drink」、お菓子を表す「sweet」のどれかに属しているとする。
・このうち「food」に属する__データの個数を知りたい時__などは、「food」に属するデータを集約してグループ化する必要がある。
・グループ化には、__df.groupby('グループ化する列の名前')__を使う。
・この時複数の列でグループ化する時は__('列1','列2'])__というふうにすれば良い。
・このgroupbyメソッドで返されるデータの形は「GroupByオブジェクト」であり、これに対して__count(),mean(),sum(),max()__などのメソッドを使うことで、グループ化したデータの個数などを求めることができる。（Pandasコースでも学習済み）

・今回の例ならば、以下のようにすれば良い。

```python
gb = df.groupby('type')
gb['food'].count()
```

#データベースからのデータ取得
##データベースからのデータ読み込み
・データベースからの読み込みは__pd.read_sql()__で行うが、引数で渡す値が特殊なものになる。
・第一引数には、読み込むデータベースのテーブルと列を以下のように指定する。

'''
SELECT
 列1,
 列2　　(最後の列には「,」はいらない)
FROM テーブル
'''

・第二引数には、接続するデータベースの情報を以下のようにまとめて渡す。

__sqla.create_engine('接続データベース+ドライバー名://接続ユーザー名:パスワード@ホスト名:ポート番号/データベース名?charset=文字コード')__

・データ読み込みの一連の流れを以下に記述する。(データベースの情報は架空のもの)

```python
import sqalchemy as sqla
#データベースの情報をまとめる
engine = sqla.create_engine('mysql+mysqldb://ngayope:ngayope@mysql-service:3307/database1?charset=utf8')
#データベース「database1」の「products」テーブルから「product_id」と「product_name」を取得
pd.read_sql('''
SELECT
 product_id,
 product_name
FROM products
''',engine)
```

##テーブルの結合
・データベースのテーブルの結合も、Excelの時と同じように、pd.merge(left,right,on=)でも行うことができるが、データベースの場合はより簡単に結合させることができる。
・結合の場合、SQLの__JOIN__を使う。
・以下に結合の方法を記載(列1をキーとして、テーブルAにテーブルBを結合する時)

'''
SELECT
 テーブルA.列1，
 テーブルB.列1
FROM
 テーブルA
 JOIN テーブルB ON テーブルA.列1 = テーブルB.列1　（追加することを記述）
'''

##データの絞り込み
・__データの絞り込み__は、__WHERE__句を使って行う。使う時はSELECT、FROMと同列で行う。
・複数の条件で絞り込みをしたい時は__「OR」「AND」__を使う。「AND」は条件全てを満たす物を抽出する。

'''
WHERE
 テーブル名.列名 = 抽出したい値1 OR
 テーブル名.列名 = 抽出したい値2
'''

・ここまでのコード（データは商品の販売年月や定価を表している）![スクリーンショット 2020-10-29 14.58.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/f9e63923-93c6-3822-50d1-bb0b09407083.png)

・上記コードの解説：
__「SELECT」__で今回出力する3つのデータを指定している。
__「FROM」__で「どの商品を販売したか」のテーブルであるmlprep_sales_productsを指定し、__「JOIN ON」__で、これとmlprep_sales,mlprep_productsを結合している。
最後に__「WHERE」__でmlprep_productsテーブルの定価を示す列「catalog_price」が200以上であるもののみ抽出している。

##データの集約
・pandasのGroupByを使った方法を説明したが、SQLにも同じ働きを持つ__GROUP BY句__があり、これを使ってデータを集約できる。
・データを集約する時は、必要に応じてデータを結合してから、そのデータを一つのテーブルに集約する。

'''
 JOIN テーブルB ON テーブルA.列1 = テーブルB.列1
GROUP BY 集約する列
'''

#まとめ
・Excelのデータ読み込みは_pd.read_excel()___、データ結合は__pd.merge()__、データ絞り込みは__df.query()__、データ集約（グループ化）は__df.groupby()__で行う。
・データベースのデータ読み込みは__pd.read_sql()__で行う。
・第一引数には、__「SELECT 列 FROM テーブル」__で読み込むテーブルと列を指定する。
・同様に、データ結合には__「JOIN」__、絞り込みには__「WHERE」__、集約には__「GROUP BY」__を使う。
・第二引数には、__sqla.create_engine()__でまとめたデータベースの情報を指定する。

今回は以上です。最後まで読んでいただき、ありがとうございました。