GCIデータサイエンティスト育成講座の解答を作ってみた(7章)

[松尾研究室のGCIデータサイエンティスト育成講座](https://weblab.t.u-tokyo.ac.jp/gci%E3%83%87%E3%83%BC%E3%82%BF%E3%82%B5%E3%82%A4%E3%82%A8%E3%83%B3%E3%83%86%E3%82%A3%E3%82%B9%E3%83%88%E8%82%B2%E6%88%90%E8%AC%9B%E5%BA%A7%E3%83%BB%E6%BC%94%E7%BF%92%E3%82%B3%E3%83%B3%E3%83%86/ "松尾研究室のGCIデータサイエンティスト育成講座")
をやってみたところ、解答が無かったので、自分で作ってみました。
間違えていたらすみません、教えて頂けると嬉しいです


<練習問題 1>
以前扱った学生のデータ（student-mat.csv）を使って、学校を選んだ理由（reason）を円グラフ化して、それぞれの割合を出してください。

```
import matplotlib.pyplot as plt
math_data=pd.read_csv("student-mat.csv",sep=";")

uniques=math_data["reason"].unique()
values=math_data["reason"].value_counts()


plt.figure(figsize=(5,3),facecolor="white")
sizes=[]
for i in range(len(uniques)):
    sizes.append(values[uniques[i]])
colors = ['yellowgreen', 'gold', 'lightskyblue', 'lightcoral']
explode = (0, 0.1, 0, 0) 
plt.pie(sizes, explode=explode, labels=uniques, colors=colors,
        autopct='%1.1f%%', shadow=True, startangle=90)
plt.axis('equal')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408729/aa856550-566b-2957-8fb4-7e929d6f718e.png)


<練習問題 2>
上記と同じデータで、higher - 高い教育を受けたいかどうか(binary: yes or no)を軸にして、それぞれの数学の最終成績G3の平均値を棒グラフで表示してください。ここから何か推測できることはありますか？

```
import matplotlib.pyplot as plt
import numpy as np

plt.figure(figsize=(4,3),facecolor="white")

X = 0
# グラフの幅
w=0.2

yes_data=math_data[math_data["higher"]=="yes"]["G3"].mean()
no_data=math_data[math_data["higher"]=="no"]["G3"]

plt.bar(X, yes_data, color='b', width=w, label='yes', align="center")
plt.bar(X + w, no_data, color='g', width=w, label="no", align="center")

# 凡例を最適な位置に配置
plt.legend(loc="best")

plt.grid(True)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408729/6e6db87b-6df1-bc25-674f-7c258d25ce31.png)


<練習問題 3>
上記と同じデータで、通学時間（traveltime）を軸にして、それぞれの数学の最終成績G3の平均値を横棒グラフで表示してください。何か推測できることはありますか？

```
# 画像の大きさとバッグカラーの設定
plt.figure(figsize=(4,3),facecolor="white")
g3_grades=math_data.groupby("traveltime")["G3"].mean()
X = g3_grades.keys()
plt.barh(X,math_data.groupby("traveltime")["G3"].mean(), align="center")
plt.ylabel("traveltime")
plt.xlabel("G3")
plt.grid(True)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408729/eeb335f4-740a-0986-915b-5c4023273cf3.png)

7.3 総合問題
7.3.1 時系列データ分析
ここでは、本章で身に付けたpandasやscipyなどを使って、時系列データついて扱っていきましょう。

（1）（データの取得と確認）下記のサイトより、dow_jones_index.zipをダウンロードし、中にあるdow_jones_index.dataを使って、データを読み込み、はじめの5行を表示してください。またデータのそれぞれのカラム情報等を見て、nullなどがあるか確認してください。　　

https://archive.ics.uci.edu/ml/machine-learning-databases/00312/dow_jones_index.zip　　

（2）（データの加工）カラムのopen、high、low、close等のデータは数字の前に$マークが付いているため、これを取り除いてください。また、日時をdate型で読み込んでいない場合は、date型に変換しましょう。

（3）カラムのcloseについて、各stockごとの要約統計量を算出してください。

（4）カラムのcloseについて、各stockの相関を算出する相関行列を出してください。また、seabornのheatmapを使って、相関行列のヒートマップを描いてみましょう。（ヒント：pandasのcorr()を使います。）

（5）(4)で算出した相関行列の中で一番相関係数が高いstockの組み合わせを抽出してください。さらに、その中でもっとも相関係数が高いペアを抜き出し、それぞれの時系列グラフを書いてください。

（6） pandasのrollingとwindow関数（窓関数）を使って、上記で使った各stockごとに、closeの過去5期（5週間）移動平均時系列データを計算してください。

（7） pandasのshift()を使って、上記で使った各stockごとに、closeの前期（1週前）との比の対数時系列データを計算してください。さらに、この中で、一番ボラティリティ（標準偏差）が一番大きいstockと小さいstockを抜き出し、その対数変化率グラフを書いてください。


```
import seaborn as sns
#(1),(2)
A=pd.read_csv("dow_jones_index.csv",sep=",")
A["high"]=A["high"].map(lambda x: float(x.split("$")[1]))
A["low"]=A["low"].map(lambda x: float(x.split("$")[1]))
A["open"]=A["open"].map(lambda x: float(x.split("$")[1]))
A["close"]=A["close"].map(lambda x: float(x.split("$")[1]))
from datetime import datetime as dt
A["date"] = A["date"].map(lambda x: dt.strptime(x, '%m/%d/%Y'))
#(3)
A.groupby("stock").close.describe()
#(4)
A_1=A.groupby("stock").close.apply(list)
df=pd.DataFrame()
key=A_1.keys()

list_df = pd.DataFrame()

for i in range(len(key)):
    tmp_se = pd.Series(A_1[key[i]])
    list_df = list_df.append( tmp_se,ignore_index=True )

list_df.index=key
list_df=list_df.T
list_df.corr()
import seaborn as sns
sns.set(style="white")
sns.heatmap(list_df.corr(),annot = False)
plt.show()
#(5)
corrs=list_df.corr()
max_value=max(corrs[corrs<1].max(1))
corrs[corrs==max_value]
plt.plot(range(len(list_df["CSCO"])),list_df["CSCO"])
plt.plot(range(len(list_df["MSFT"])),list_df["MSFT"])
#(6)
N=5 #N期を決定
AA=(list_df["AA"].rolling(N).sum()/N).dropna()
print(AA) #N期のデータ、株式"AA"
#(7)
stds=[]
np.log(AA/AA.shift()).std()
for i in range(len(key)):
    ABC=(list_df[key[i]].rolling(N).sum()/N).dropna()
    stds.append(np.log(ABC/ABC.shift()).std())
stds=np.array(stds)
print(stds[np.argmax(stds)],stds[np.argmin(stds)])
i=np.argmax(stds)
ABC=(list_df[key[i]].rolling(N).sum()/N).dropna()
np.log(ABC/ABC.shift())
plt.plot(range(len(np.log(ABC/ABC.shift()))),np.log(ABC/ABC.shift()))
i=np.argmin(stds)
ABC=(list_df[key[i]].rolling(N).sum()/N).dropna()
np.log(ABC/ABC.shift())
plt.plot(range(len(np.log(ABC/ABC.shift()))),np.log(ABC/ABC.shift()))
```

### 7.3.2 マーケティング分析

次は、マーケティング分析でよく扱われる購買データです。一般ユーザーとは異なる法人の購買データですが、分析する軸は基本的に同じです。

（1）下記のURLよりデータをpandasで読み込んでください（件数50万以上のデータで比較的大きいため、少し時間がかかります。）

    http://archive.ics.uci.edu/ml/machine-learning-databases/00352/Online%20Retail.xlsx"
    
    (ヒント)pd.ExcelFileを使って、シートを.parse('Online Retail')で指定してください。
    
    また、今回の分析対象は、CustomerIDにデータが入っているレコードのみ対象にするため、そのための処理をしてください。さらに、カラムのInvoiceNoには数字の前にCがあるものはキャンセルのため、このデータを取り除いてください。他にもデータとして取り除く必要なものがあれば、適宜処理してください。以下、このデータをベースに分析していきます。

（2）このデータのカラムには、購買日時や商品名、数量、回数、購買者のIDなどがあります。ここで、購買者（CustomerID）のユニーク数、バスケット数（InvoiceNoのユニーク数）、商品の種類（StockCodeベースとDescriptionベースのユニーク数）を求めてください。

（3）このデータのカラムには、Countryがあります。このカラムを軸に、それぞれの国の購買合計金額（単位あたりの金額×数量の合計）を求め、降順にならべて、上位5つの国の結果を表示してください。

（4）上の上位5つの国について、それぞれの国の商品売り上げ（合計金額）の月別の時系列推移をグラフにしてください。ここで、グラフは分けて表示してください。

（5）上の上位5つの国について、それぞれの国における商品の売り上げTOP5の商品を抽出してください。また、それらを国ごとに円グラフにしてください。なお、商品は「Description」ベースで集計してください。

```
import pandas as pd 
#(1)
excel =pd.ExcelFile('Online Retail.xlsx')
df = pd.DataFrame()
sheetdf = excel.parse('Online Retail')
A=sheetdf
B=A.index[A["CustomerID"].isnull()]
A=A.drop(B)
BA=A["InvoiceNo"].str.startswith('C')
BA=BA.fillna(False)
BA=A.index[BA]
A=A.drop(BA)
"""
（2）このデータのカラムには、購買日時や商品名、数量、回数、購買者のIDなどがあります。ここで、購買者（CustomerID）のユニーク数、
バスケット数（InvoiceNoのユニーク数）、商品の種類（StockCodeベースとDescriptionベースのユニーク数）を求めてください。
"""
print(A["InvoiceNo"].describe())
A["CustomerID"]=A["CustomerID"].map(lambda x: int(float(x)))
print("CustomerIDのユニーク数:",len(A["CustomerID"].unique()))
print("StockCodeのユニーク数:",len(A["StockCode"].unique()))
print("Descriptionのユニーク数:",len(A["Description"].unique()))
"""
（3）このデータのカラムには、Countryがあります。このカラムを軸に、それぞれの国の購買合計金額（単位あたりの金額×数量の合計）を求め、
 降順にならべて、上位5つの国の結果を表示してください。
"""
Each_country=A.groupby("Country")["UnitPrice"].sum().map(lambda x : int(x))
Each_country.sort_values(ascending=False)[:5]
"""
（4）上の上位5つの国について、それぞれの国の商品売り上げ（合計金額）の月別の時系列推移をグラフにしてください。ここで、グラフは分けて表示してください。

"""
for i in range(len(Each_country_name)):
    A["Date"]=A[A["Country"]==Each_country_name[i]]["InvoiceDate"].map(lambda x:"{}-{}".format(x.year,x.month))

import matplotlib.pyplot as plt 
plt.figure(figsize=(20,15))
for i in range(len(Each_country_name)):
    ax=plt.subplot(5,1,i+1)
    prices=A[A["Country"]==Each_country_name[i]].groupby("Date")["UnitPrice"].sum()
    ax.plot(prices.keys(), prices)
    plt.title("{}".format(Each_country_name[i]),size=20)

"""
（5）上の上位5つの国について、それぞれの国における商品の売り上げTOP5の商品を抽出してください。
また、それらを国ごとに円グラフにしてください。なお、商品は「Description」ベースで集計してください。
"""
for i in range(len(Each_country_name)):
    items=A[A["Country"]==Each_country_name[i]]["Description"].value_counts()[:5]
    print("{}のTOP5:".format(Each_country_name[i]))
    for k in range(5):
        print("TOP{}".format(k+1),items.keys()[k])

```