#author("2023-10-23T08:47:35+09:00","default:cmdsadmin","cmdsadmin")
[[第4回]]
#author("2024-05-07T10:37:41+09:00","default:cmdsadmin","cmdsadmin")

* 第4回演習課題 [#w3bb626b]


[[課題提出]]のページを熟読したうえで,以下の演習課題に取り組みなさい

** 基礎問題 [#e586be99]
【注意】課題提出サイトにおいては,選択肢の順番がシャッフルされることがあるので注意してください.

''Q4-1【箱ひげ図】''
- 箱ひげ図について正しい記述をすべて選びなさい
-- a. 箱の内部に引かれる横線は平均値を表す
-- b. Pythonの箱ひげ図において,箱から上方向に伸びたひげの上端は,最大値,または,第3四分位から1.5IQRの点を表す
-- c. 箱の底辺は第2四分位を表す
-- d. 箱ひげ図はデータのばらつき具合を可視化するのに役立つ
-- e. 箱ひげ図のひげの外に現れる外れ値は,統計的におかしい値なので必ず除去する必要がある

''Q4-2【ヒストグラム】''
- ヒストグラムについて正しい記述をすべて選びなさい
-- a. ヒストグラムは棒グラフの一種であり,データの大きさを比較するのに用いられる
-- b. ヒストグラムの横軸は「階級」を表し,縦軸はその階級に属するデータの「度数」を表す
-- c. ヒストグラムの階級の幅を細かくしていくと,確率分布関数の形に近づいていく
-- d. ヒストグラムの階級の幅を細かくしていくと,確率密度関数の形に近づいていく
-- e. ヒストグラムの最も度数の多い階級をメジアンという

''Q4-3【相関係数】''
- 相関係数について正しい記述をすべて選びなさい
-- a. 相関係数は-1.0から1.0の範囲の値をとる
-- b. 相関係数は値が小さいほど2つの変数間に相関がないことを示す
-- c. 期末試験のデータで,数学の点数と理科の点数の相関係数が高かったので,「理科が得意な人は,数学が得意なことがその理由にある」と断定できる
-- d. 相関係数は外れ値に大きな影響を受けやすい
-- e. 相関係数が-0.7の2変数を散布図にプロットすると,右肩下がりの分布になる

''Q4-4【データの整形】''
- 下記に示す[[神戸の気象データ(2022年10月~2023年9月)>データ#ve3d3dee]]を読み込み,データの整形を行いなさい
-- https://www2.cmds.kobe-u.ac.jp/~masa-n/dshandson/kobe_weather_202210_202309.csv

【データの整形】
+ pandasのデータフレームに読み込む
+ 各列の型をチェックする
+ 日付の列をdatetime型に変換
+ 最大風速風向,天気概況・昼の列をcategory型に変換
+ 日付の列をインデクスにセット

【プログラムのスケルトン】
 # Pandasをインポート
 import pandas as pd
 
 #1. pandasのデータフレームに読み込む
 data = pd.###########("https://www2.cmds.kobe-u.ac.jp/~masa-n/dshandson/kobe_weather_202210_202309.csv", encoding="UTF-8")
 #オリジナルのデータをコピーしておく
 df = data.copy()
 
 #2. 各列の型をチェックする
 print("【整形前】\n", df.dtypes)
 
 #3. 日付の列をdatetime型に変換
 df["日付"] = pd.###############(df["日付"])
 
 #4. 最大風速風向,天気概況・昼の列をcategory型に変換
 df["最大風速風向"] = df["最大風速風向"].########("#######")
 df["天気概況・昼"] = df["天気概況・昼"].########("#######")
 
 #5. 日付の列をインデクスにセット
 df = df.###########("日付")
 
 #再び,各列の型をチェックする
 print("【整形後】\n", df.dtypes)
 
 #確認
 df


''Q4-5【データの欠損値処理】''
- Q4-4で整形したデータの欠損値を数えた (df.isnull().sum()) ところ,以下のような結果となった.
 平均気圧        0
 合計降水量    187 
 平均気温        0
 最高気温        0
 最低気温        0
 平均湿度        0
 最大風速        1
 最大風速風向    1
 日照時間        2
 天気概況・昼    0

- 各変数の欠損値について,それぞれ以下のように穴埋めを行いなさい
+【合計降水量】 0で埋める
+【最大風速】 前後の値の線形補間で埋める
+【最大風速風向】 同月の最も頻度の高い風向で埋める
+【日照時間】 前日の日照時間で埋める

 #ここから
 #
 # Q4-4のコードをそのまま貼り付ける
 #
 #ここまで

 #欠損値をチェックする
 print("【欠損値】\n", df.isnull().sum())

 #【合計降水量】 欠損値を0で埋める
 df["合計降水量"] = df["合計降水量"].########(#)

 #【最大風速】 欠損値を線形補間で埋める
 df["最大風速"] = df["最大風速"].##########()

 #【日照時間】 前日の日照時間で埋める
 df["日照時間"] = df["日照時間"].#######(###########)

 #【最大風速風向】欠損している日付のデータを見つける
 df[df["最大風速風向"].isnull()]

 #その月の最大風速風向の最頻値を見つける
 df.loc["20##-##-##":"20##-##-##", "最大風速風向"].#######()

 #見つかった最頻値で埋める
 df.loc["20##-##-##", "最大風速風向"] = "######"

 #再びチェックする
 print("【欠損値処理後】\n", df.isnull().sum()) 

** 応用問題 [#s5d196b8]

''Q4-6 【卸売業者のデータを眺める】''

- [[卸売業者(Wholesale customers)データセット>データ#fba1d3b3]]は,ポルトガルのある食料品卸売業者の年間売上額をまとめたものである.
-- https://www2.cmds.kobe-u.ac.jp/~masa-n/dshandson/wholesale_customers.csv

【データの説明】
- データの各行は,1つの顧客に対する食品種類別の年間売上額を表している.
- データの各列は以下の通りである.
 #0: Channel: 販売チャンネル
    1: Horeca (ホテル,レストラン,カフェ)
    2: Retail (小売店)
 #1: Region: 消費地域
    1: リスボン
    2: ポルト
    3: その他
 #2: Fresh: 生鮮品の年間売上
 #3: Milk: 乳製品の年間売上
 #4: Grocery: 食料雑貨の年間売上
 #5: Frozen: 冷凍品の年間売上
 #6: Detergents_Paper: 洗剤,紙製品の年間売上
 #7: Delicatessen: 惣菜の年間売上



- このデータに対してEDAを行い,次のRQ1~RQ6に答えなさい.

- RQ1: Channel,Regionのそれぞれについて,データが何件あるか?
 Channel
    1 (Horeca): ___ 件
    2 (小売店): ___ 件
 Region
    1 (リスボン): ___ 件
    2 (ポルト): ___ 件
    3 (その他): ___ 件 

- RQ2: 売上合計額が多い品目を,大きいものから順に3つ挙げよ.また,それぞれの額を答えなさい.
※ヒント:データフレームを合計関数sum()で要約する
 1位: __(品目)__ __(金額)__
 2位: __(品目)__ __(金額)__
 3位: __(品目)__ __(金額)__

- RQ3: Horecaと小売店について,売上合計額が多いのはどちらか?品目ごとに答えなさい.
 Fresh: Horeca/小売店
 Milk: Horeca/小売店
 Grocery: Horeca/小売店
 Frozen: Horeca/小売店
 Detergents_Paper: Horeca/小売店
 Delicassen: Horeca/小売店

- RQ4: リスボンとポルトについて,店舗当たりの(平均)売上額が大きいのはどちらか?品目ごとに答えなさい.
 Fresh: リスボン/ポルト
 Milk: リスボン/ポルト
 Grocery: リスボン/ポルト
 Frozen: リスボン/ポルト
 Detergents_Paper: リスボン/ポルト
 Delicassen: リスボン/ポルト

- RQ5: Groceryの売上に最も相関のある品目は何か?また,相関係数の値は?
 ___(品目)___ 
 ___(相関係数)___ 

- RQ6: それぞれの品目において,最も売り上げの高い店を見つけ,その行番号(インデクス)を求めなさい
 Fresh: __________
 Milk: __________
 Grocery: __________
 Frozen: __________
 Detergents_Paper: __________
 Delicassen: __________

【プログラムのスケルトン】
 
 #準備(すべてに共通)
 # PandasとNumpyをインポート
 import pandas as pd
 import numpy as np
 
 # 日本語化Matplotlibもインポート
 import matplotlib.pyplot as plt
 # ↓の1行は提出時には削除すること
 !pip install japanize-matplotlib
 import japanize_matplotlib
 
 # Seabornもインポート
 import seaborn as sns
 
 # pickleをインポート(モデルの保存用)
 import pickle
 
 #データを取得
 data = pd.read_csv("https://www2.cmds.kobe-u.ac.jp/~masa-n/dshandson/wholesale_customers.csv")
 
 #オリジナルデータをコピーしておく
 df = data.copy()
 df
 #以降,EDAを行う

''Q4-7 【ポルトの購買層】''

- ポルトにおける販路拡大のため,既存顧客の把握を行いたい.
- ポルトの全チャネルの売り上げデータに対して,階層的クラスタリングを行い,顧客の類型化を行う.下記のステップに従ってクラスタリングを行うPythonプログラムを完成させなさい
-- Step1: 全データから,Regionが2 (ポルト)のデータを抽出し,ChannelとRegionの列を除外して,df2とする
-- Step2: df2に標準化を適用し,df2_scを得る
-- Step3: クラスタ数を指定せずに,df2_scに対して階層的クラスタリングを適用し,デンドログラムを描く
-- Step4: クラスタ数を7として,df2_scに階層的クラスタリングを適用し,df2にクラスタの列を付与する
-- Step5: クラスタ毎にdf2のデータを表示・要約する

【プログラムのスケルトン】

 ### Q4-6からそのまま再利用
 #準備(すべてに共通)
 # PandasとNumpyをインポート
 import pandas as pd
 import numpy as np
 
 # 日本語化Matplotlibもインポート
 import matplotlib.pyplot as plt
 # ↓の1行は提出時には削除すること
 !pip install japanize-matplotlib
 import japanize_matplotlib
 
 # Seabornもインポート
 import seaborn as sns
 
 # pickleをインポート(モデルの保存用)
 import pickle
 
 #データを取得
 data = pd.read_csv("https://www2.cmds.kobe-u.ac.jp/~masa-n/dshandson/wholesale_customers.csv")
 
 #オリジナルデータをコピーしておく
 df = data.copy()
 df
 ### ここまで #####
 
 # デンドログラムを描く関数(基本的に触らないこと)
 from scipy.cluster.hierarchy import dendrogram
 def plot_dendrogram(model, **kwargs):
     counts = np.zeros(model.children_.shape[0])
     n_samples = len(model.labels_)
     for i, merge in enumerate(model.children_):
         current_count = 0
         for child_idx in merge:
             if child_idx < n_samples:
                 current_count += 1  # leaf node
             else:
                 current_count += counts[child_idx - n_samples]
         counts[i] = current_count
 
     linkage_matrix = np.column_stack(
         [model.children_, model.distances_, counts]
     ).astype(float)
     dendrogram(linkage_matrix, **kwargs)
 ### ここまで

 #Step1. ポルトのデータに絞って,df2を得る
 # dfからRegionが2の行と,"Fresh"以降の列を取り出す
 df2 = df.loc[df[#######]==##, "Fresh":].copy()
 #確認する
 print("【ポルトの売上データ】\n", df2.head(10))
 
 #Step2. 標準化する
 from sklearn.preprocessing import StandardScaler
 sc = ##############()
 # 標準化して,データフレームに入れる
 df2_sc = pd.DataFrame(sc.fit_transform(#####), index=########, columns=#########)
 # 確認する
 print("\n【標準化したデータ】\n", df2_sc.head(10))


 # Step3. 階層的クラスタリングを適用し,デンドログラムを描く
 #凝集型階層的クラスタリングのモデル
 from sklearn.cluster import AgglomerativeClustering
 #クラスタ数の指定なし.distance_threshold=0 とすると,最後までクラスタリングを続ける
 model = AgglomerativeClustering(n_clusters=None, distance_threshold=0)
 #標準化したデータで学習.教師なしなので,yが不要
 model.fit(#######)
 #デンドログラムを描画する
 plot_dendrogram(#######, labels=df2.index)

 #Step4. 上記のデンドログラムを参考に,クラスタ数を7でクラスタリングする
 k = 7
 model2 = AgglomerativeClustering(n_clusters=####)
 model2.fit(#######)
 #元データにクラスタのラベルを付けてみる
 df2["クラスタ"] = model2.#########
 print("\n【クラスタリング結果】\n", df2.head(10))


 # Step5. クラスタ毎にデータを表示・要約する
 #各クラスタの内容を表示する
 for i in range(###):
   print(f"\n\n【クラスタ No. {i}】")
   print(df2[df2["クラスタ"]==i])
 
 #各クラスタの記述統計量(平均)を計算して表示
 df_mean = df2.########("#########").mean()
 print("\n【各クラスタを平均で要約】\n", df_mean)
 
 #積み上げ棒グラフでプロットする(オプショナル)
 #df_mean.plot.bar(stacked=True)


** 発展問題 [#saf97b3d]

''Q4-8 【特異な顧客を見つける】''
- Q4-6の全顧客の中から,''最も特異な顧客'' を発見し,その顧客のデータの行番号(インデクス)を答えなさい.
-- 最も特異な顧客とは,売上に関する特徴が,他のどの顧客とも最も遠い顧客1つを指すものとする
- また,その顧客をどのように発見したか,簡単なレポートにまとめること
- Q4-8のために作成したipynbファイルを提出すること


トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS