wasedaデータコンペ 記録

早稲田のデータコンペまとめ

概要
・大学生の関心のある話題の割合ランキング上位5項目を見たところファッションが含まれていた
・ファッションへの価値観は新型コロナウイルス前と後であまり変化がないと考え有用性があると判断

データについて
・データ：ADK生活者総合調査2018
・調査対象：職業に関する質問で(column番号13)大学生大学院生と答えた関東、関西に住む737人
・抽出した質問項目：アンケート結果の中からファッションの価値観を左右する重要な項目（下）

a(911):気に入ったものならば中古品やリサイクルでもかまわない
b(912):品質・機能をしっかり比較検討して購入する
c(915):snsやブログ、サイトなどで推奨されているものを購入することが多い
d(918):多くの人が使用している商品であるかどうかが大切だと思う
e(1406):ファッション雑誌をよく読む
f(1411):有名人などのファッションや髪形メイクを参考にする
g(1414):常に最新のファッションを身に着けたい
h(1416):購入している服や靴のブランドにはこだわりがある
i(!416):ファッションで自分らしさを表現したい
j(1435):ブランドは金額が高いほど品質が良いと思う
k(1436):高級ブランドはセールや海外通販などでできるだけ安く手に入れたい
l(1442):ベーシックで無難なファッションが好きなほうだ
m(1442):ゴージャスで主張のあるブランド、アイテムを持っておきたい
n(1444):ファストファッションもよく取り入れている
o(1528):ファストファッションイノベーター度
p(1862):異性から魅力的だと思われたい
p(1885):ファッションやおしゃれに気を使っている
q(1888):ファッションにはこだわりがある

分析の流れ
1,因子の抽出
・第一因子：全体的なファッションへの関心度
・第二因子：ベーシックで無難なファッションへのこだわり
・第三因子：品質や機能の重要度
・第四因子：SNSなどの情報からファッションを決める傾向

抽出プロセス→因子数を決定するために主成分分析を行い固有値を求めた今回の分析ではガットマン基準及び累積寄与率が60％以上の基準で因子数を求めた結果前者は因子数3,後者は因子数5であった。そこで因子数3~5で分析を進めた結果因子数4の場合が因子ごとの特徴を把握しやすかったため採用した。

2,抽出された因子をもとにクラス数の決定
(ウォード法で階層的クラスター分析を行った.図で表してみるとクラス数5であれば切れ味よく分類できると考えた)
3,5クラスへの分類
　得られた因子得点のままクラスター分析を行う方法とデータを標準化してクラスター分析を行う方法があるが今回は後者を採用。kmeans++法を用いて5クラスへ対象者を割り振る
kmeans法とkmeans++法の簡単な違い、説明
はじめにkmean法もkmeans++法も設定されたクラス数をもとにf=ΣΣabs(xi-vj)(1<=j<=k)(xi∈Cj)
kmeans法：標準的なk-means法においてはランダムにクラスター中心が割り当てられアルゴリズムが進む。1,各店xiに対してランダムにクラスタを割り振る。2,各クラスタに割り当てられた点について重心を計算する。各点について上記で計算された重心からの距離を計算し距離が一番近いクラスタに割り当て直す。問題点は最初にランダムにクラスタを割り振るためその初期値によって最適とはかけ離れたクラスタリングがなされてしまう可能性がある。この克服を目指しす→kmeans++法
kmeans++法：クラスター中心を選ぶ際に重み付き確率分布を用いることでk-means法での初期値依存を解消できる。なお、初期値の選び方はk-means法と同じ

その他具体的なことは割愛、、

各クラスの説明
決定木分析
決定木で統計モデルを作成したところ精度95％以上で5つのクラスへ分類できることがわかった。
木の深さは5に設定

考察と今後の展望
商品を売る際にどの価値観を持つ消費者をターゲットにするのか絞りたい。あなたがどういったファッションへの意識を持ちどんな消費行動をし、どんな生活価値観があるのかについての質問をすることで５つのクラスのいずれかに分類することができる。
大学生が多いある地域にある層向けの洋服店がなかったとする。その層向けの店を作れば成功できるかもしれない。

以下コード

```python
"""
今回の調査では大学生を対象とすることにした
"""
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
import sklearn
from sklearn.linear_model import LogisticRegression
from sklearn.linear_model import LinearRegression
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import mean_squared_error
#対象は職種で大学生大学院生と選んだ人
df1=pd.read_csv("parts-file01.csv",usecols=[13])
df1=df1[df1["AAAA"]==11]
#消費意識の質問項目を抽出
df2_1=pd.read_csv("parts-file02.csv",usecols=[16,17,20,23])
#ファッション意識の質問項目を抽出
df2_2=pd.read_csv("parts-file03.csv",usecols=[12,17,20,22,38,41,42,43,48,50,134])
#生活意識、価値観の質問項目を抽出
df2_3=pd.read_csv("parts-file05.csv",usecols=[15,38,41])
#0列目に大学生大学院生、１列目以降に質問項目
df3=pd.concat([df1,df2_1,df2_2,df2_3],axis=1)
df3=df3.dropna()
len(df3)
#"AAAA"の列を削除しindex番号を振る
df_new=df3.drop("AAAA",axis=1)
df_new=df_new.reset_index(drop=True)
#見やすいようにrenameする
df_new=df_new.rename(columns={"CBAA_1":"","CBAA_2":"",})
df_new
"""
設問数が18と多いので設問を制約する
そのために因子分析を行う
まずは因子数を決定する
"""
#データの標準化を行い異なる変数間で大小が評価できるようにする
from sklearn.preprocessing import StandardScaler
ss=StandardScaler()
df_new_s=pd.DataFrame(ss.fit_transform(df_new))
df_new_s
"""
因子数を決定するために主成分分析で求めることができる固有値を計算する
"""
from sklearn.decomposition import PCA
pca=PCA()
pca.fit(df_new_s)
ev=pca.explained_variance_
pd.DataFrame(
    ev,index=["PC{}".format(x+1) for x in range(len(df_new.columns))],
    columns=["固有値"]
)
"""
計算された固有値をもとにスクリープロットを描く
"""
#固有値１の基準線
ev_1=np.ones(17)
#変数を指定
plt.plot(ev,"s-")#主成分分析による固有値
plt.plot(ev_1,"s-")#ダミーデータ
#軸名を指定
plt.xlabel("Number of factors")
plt.ylabel("Eigenvalue")
plt.grid()
plt.show()
"""
因子数の決定基準はいくつかあるが、今回はガットマン基準(固有値が1以上の因子を採用)を使って
推定する。その場合、上のスクリーンプロットから因子数は4とすることができる
ガットマン基準により因子数を推定できたが一応累積寄与率が60％以上となる因子数も見てみる
"""
#寄与率を取得
evr=pca.explained_variance_ratio_
#見やすいように行名列名を付与してデータフレームに変換
pd.DataFrame(evr,
            index=["PC{}".format(x+1) for x in range(len(df_new.columns))],
            columns=["寄与率"])
#寄与率の累積値をプロット
plt.plot([0]+list(np.cumsum(evr)),"-o")
plt.xlabel("Number of PC")#主成分の数
plt.ylabel("Cumsum")#累積寄与率
plt.grid()
plt.show()
"""
・ガットマン基準：4
・寄与率60％以上で因子を採用:6
今回の分析では前者を選択しようと思う
つまり因子数を4に決定
"""
"""
続いて得られた結果をもとに因子分析を行う
"""
#sklearnのFactorAnalysis(因子分析)クラスをインポート
from sklearn.decomposition import FactorAnalysis as FA
#因子数を指定
n_components=4
#因子分析の実行
fa=FA(n_components,max_iter=5000)#モデルを定義
df_new_pro=fa.fit_transform(df_new_s)#fitとtransformを一括処理
#737人の因子得点の行列
print(df_new_pro)
print(df_new_pro.shape)
#因子負荷量行列の取得(共通因子が各変数に与える影響度)
print(fa.components_.T)
"""
18の設問に対する各因子の解釈を行う
各因子の解釈はEvernoteの５－２に書いた
"""
#変数Factor_loading_matrixに格納
Factor_loading_matrix=fa.components_.T
#因子の解釈をやりやすくするためデータフレームに変換
Factor_loading_matrix=pd.DataFrame(
Factor_loading_matrix,columns=["第一因子","第二因子","第三因子","第四因子"],
index=[df_new_s.columns])
Factor_loading_matrix
"""
解釈が行いやすいようにグラフでも見てみる
縦が因子得点、横が質問番号
"""
import japanize_matplotlib
Factor_loading_matrix.plot(figsize=(9,9))
"""
続いて、新たに得られた因子得点のデータをもとに大学生をいくつかのクラスターに分類する
クラスター分析を行う
"""
#まずはデータの情報をデータフレームで再度確認する
df_new_pro=pd.DataFrame(
df_new_pro,columns=["第一因子","第二因子","第三因子","第四因子"],
)
df_new_pro
#ほかの情報も確認
df_new_pro.describe()
"""
因子得点のままクラスター分析を行う方法とデータを標準化してクラスター分析を行う方法があるが
今回は後者を採用
"""
#データの標準化を行い各質問の情報量の統一を行う
from sklearn import preprocessing
ss=preprocessing.StandardScaler()
df_new_pro_s=pd.DataFrame(ss.fit_transform(df_new_pro))
df_new_pro_s
"""
クラスタ分析を行い大学生大学院生のファッション価値観の特徴を分類する
階層的クラスター分析でモデルの可視化をすることでクラスター数を決定しようと思う
"""
#まずは適当なクラスター数を探す
from scipy.cluster.hierarchy import linkage,dendrogram
#ユークリッド距離、ウォード法で階層的クラスター分析を行う
#ウォード法：２つのクラスターp,qを結合したと仮定したとき
#それにより移動したクラスターの重心とクラスター内での重心とそれぞれの
#サンプルとの距離の二乗和の差が最小となるようなクラスター同士を結合する手法
df_new_pro_s_hclust=linkage(df_new_pro_s,
                           metric="euclidean",method="ward")
plt.figure(figsize=(12,8))
dendrogram(df_new_pro_s_hclust)
plt.savefig("figure_1.png")
plt.show()
"""
上の階層をみると5つのクラスだと切れ味よく分類できると考えた
故にクラス数を５として非階層クラスター分類を行う
そのさいkmeans++法を使おうと思う(kmeansはクラスタ中心が初期値に依存するが、kmeans++法では初期値に依存しない
kmeans法でも試してみる
"""
from sklearn.cluster import KMeans
#pandasからnumpyの行列に変更し行列を出力
df_new_pro_s_ar=df_new_pro_s.values
#クラスター数は5とするまたkmeans++法を使う
km=KMeans(n_clusters=5,init="k-means++",n_init=10,
         max_iter=300,tol=1e-04,random_state=0)
km.fit(df_new_pro_s_ar)
df_new_pro_s_arhat=km.predict(df_new_pro_s_ar)
print(df_new_pro_s_arhat)
"""
この結果からどのクラスにも同じくらい人がいることがわかる
"""
#割り当てられた結果をはじめのデータ(df_new_pro)にクラスター分析idとして一列追加して出力
df_new_pro_clust=df_new_pro[:]
df_new_pro_clust["ID"]=df_new_pro_s_arhat
#各クラスターの数を出力
print(df_new_pro_clust["ID"].value_counts())
df_new_pro_clust
"""
続いて回答の偏りがどこにでたのか調べる
"""
#クラスターIDでグループ化し数値を書き出す
df_new_pro_clust_gp=df_new_pro_clust.groupby("ID")
#そしてグループ別に各因子得点の合計を出す
df_new_pro_clust_gp_sm=df_new_pro_clust_gp.sum().T
df_new_pro_clust_gp_sm
#各グループの最大値を黄色でマーキング
df_new_pro_clust_gp_sm.style
def highlight_max(s):
    is_max= s==s.max()
    return ["background-color:yellow" if v else ''for v in is_max]
#各グループの最小値は緑色でマーキング
def highlight_min(s):
    is_min= s==s.min()
    return ["background-color:green" if v else ''for v in is_min]
df_new_pro_clust_gp_sm.style.apply(highlight_max)
#ちなみに縦が5つの因子、横がクラスID
df_new_pro_clust_gp_sm.style.apply(highlight_min)
df_new_pro_clust_gp_sm=df_new_pro_clust_gp_sm
df_new_pro_clust_gp_sm.style.bar(color="#4285F4")
"""
最後に決定木を作成することで新しいデータから各クラスへ分類する過程をみる
"""
#最初のデータ
train_y=np.array(df_new_pro_clust["ID"].values)
#IDをいったん削除したデータ
X=df_new_pro_clust.drop("ID",axis=1).values
print(X)
X_train,X_test,y_train,y_test=train_test_split(X,train_y,random_state=0)
from sklearn.model_selection import train_test_split
#決定木で統計モデルを作成
from sklearn import tree
#木の深さは5に設定
dtc=tree.DecisionTreeClassifier(criterion="entropy",max_depth=5,random_state=0)
dtc.fit(X_train,y_train)
print("正解率(train):{:.3f}".format(dtc.score(X_train,y_train)))
print("正解率(test):{:.3f}".format(dtc.score(X_test,y_test)))
#モデルの可視化
from sklearn.tree import plot_tree
plt.figure(figsize=(30,30))
plot_tree(dtc,filled=True)

"""