Python実践データ分析100本ノック作業記録【第一章その1】

# 目的
買ったばかりで使っていなかった本を実践し、データ分析への知見を深める。
特に現在製造業におけるデータ分析を行っているため、得るものは大きそうだと感じた。

# 環境

## 開発環境
IDE： PyCharm Community Edition
Jupyter notebookの出力は本に書いてあるため、コンソールで実行したときにどのような差分が出るかが気になったためあえて素のPyCharmを使った。

## 使用書籍

https://www.amazon.co.jp/dp/B07ZSGSN9S/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

# ノック内容

## 1本目
本と同じだから割愛……したかったのだが、この時点で色々変わってきた。
大きな差分は次の通り。

・コンソールだとDataFrame.head()単体だと表示されず、きちんとprintで出力する必要がある。
・横幅の問題か、print文では全部表示されなかった。

横幅を全部表示したい場合は次のリンクの通り、設定を触ってあげる必要がある。

https://medium.com/music-and-technology/pandas-dataframe%E3%81%AE%E8%A1%A8%E7%A4%BA%E3%82%92%E7%9C%81%E7%95%A5%E3%81%97%E3%81%9F%E3%81%8F%E3%81%AA%E3%81%84%E6%99%82-cda70f79cadc

このコードが

```python:knock1.py
import pandas as pd

customer_master = pd.read_csv(r"chap1\customer_master.csv")
pd.set_option("display.max_columns", len(customer_master.columns))
print(customer_master.head())

```

こう出力される。折り返されるのか。

```
  customer_id customer_name    registration_date customer_name_kana  \
0    IK152942        平田 裕次郎  2019-01-01 00:25:33          ひらた ゆうじろう   
1    TS808488         田村 詩織  2019-01-01 01:13:45            たむら しおり   
2    AS834628         久野 由樹  2019-01-01 02:00:14             ひさの ゆき   
3    AS345469          鶴岡 薫  2019-01-01 04:48:22           つるおか かおる   
4    GD892565         大内 高史  2019-01-01 04:54:51           おおうち たかし   

                         email gender  age      birth pref  
0  hirata_yuujirou@example.com      M   29  1990/6/10  石川県  
1    tamura_shiori@example.com      F   33  1986/5/20  東京都  
2      hisano_yuki@example.com      F   63   1956/1/2  茨城県  
3   tsuruoka_kaoru@example.com      M   74  1945/3/25  東京都  
4   oouchi_takashi@example.com      M   54   1965/8/5  千葉県  
```

## ノック2
実務を考えた場合、結合するファイルはlist[DataFrame]の形で取得したほうが良さそうだ。
そうなると、こんな感じのコードになるだろうか。globあたりで取る方が丁寧か。
個人的には、transaction_path→transaction_frame→union_transactionのように段階を踏んで定義したほうが
可読性が高く、良いコードだと思う。

``` python:knock2.py
import pandas as pd

transaction_path = [f"chap1\\transaction_{i}.csv" for i in range(1, 3)]
transaction_detail_path = [f"chap1\\transaction_detail_{i}.csv" for i in range(1, 3)]

transaction_frame = [pd.read_csv(filepath) for filepath in transaction_path]
transaction_detail_frame = [pd.read_csv(filepath) for filepath in transaction_detail_path]

union_transaction = pd.concat(transaction_frame, ignore_index=True)
print(f"{len(union_transaction)} rows")
print(union_transaction.head())

print("\n" + "-" * 20 + "\n")

union_transaction_detail = pd.concat(transaction_detail_frame, ignore_index=True)
print(f"{len(union_transaction_detail)} rows")
print(union_transaction_detail.head())

```

## ノック3
SQLの知識が半端にあったからそれを元にこんなふうに試してみたらこんなエラー。

```python
joined_dataframe = union_transaction_detail.join(union_transaction, on="transaction_id")
```

> Traceback (most recent call last):
  File "D:\Python_Project\100knocks\chapter1\knock3.py", line 12, in <module>
    joined_dataframe = union_transaction_detail.join(union_transaction, on="transaction_id")
  File "D:\Python_Project\100knocks\venv\lib\site-packages\pandas\core\frame.py", line 8110, in join
    return self._join_compat(
  File "D:\Python_Project\100knocks\venv\lib\site-packages\pandas\core\frame.py", line 8135, in _join_compat
    return merge(
  File "D:\Python_Project\100knocks\venv\lib\site-packages\pandas\core\reshape\merge.py", line 74, in merge
    op = _MergeOperation(
  File "D:\Python_Project\100knocks\venv\lib\site-packages\pandas\core\reshape\merge.py", line 672, in __init__
    self._maybe_coerce_merge_keys()
  File "D:\Python_Project\100knocks\venv\lib\site-packages\pandas\core\reshape\merge.py", line 1193, in _maybe_coerce_merge_keys
    raise ValueError(msg)
ValueError: You are trying to merge on object and int64 columns. If you wish to proceed you should use pd.concat

priceの列をデバッガで除いてみるとdtypeがint64。ここらへんが悪さをしているのかも？
とりあえず今回は本の通りpd.mergeを使い、余裕があればソース見てみることにする。

もともとソースは書き写さないでやっているのでノック4は3とほぼ同じ。省略する。

## ノック5

ノック4までのデータをこうしてみたら、

```python
joined_dataframe["calc_price"] = joined_dataframe["item_price"] * joined_dataframe["quantity"]

print(joined_dataframe[["item_price", "transaction_id", "quantity", "price", "calc_price"]].head())
```

こうなった……？

```
   item_price transaction_id  quantity   price  calc_price
0      210000    T0000000113         1  210000      210000
1      210000    T0000003439         1  420000      210000
2      210000    T0000003439         1  420000      210000
3      210000    T0000000116         1  210000      210000
4      210000    T0000000832         1  210000      210000
```

妙だったのでノック3から読んでいくと、priceは各transactionごとの合計金額のため、
結合を行うときは外したほうが良かったらしい。

joined_dataframe["calc_price"].sum()とunion_transaction["price"].sum()が一致したのでとりあえず一安心。


とりあえずここまで。体力と精神力が残っていれば今週の土日には1章を片付けておきたい。