【SPSS】Modelerでコレスポンデンス分析をする方法

【SPSS】Modelerでコレスポンデンス分析をする方法

コレスポンデンス分析とは?についてはこちら

商品企画やマーケティング部に方々から、コレスポンデンス分析(コレポン、対応分析)のご要望をいただくことがあります。

Modelerの標準機能には無いため、IBM SPSSの別製品であるStatistics(IBM SPSS Statistics Base + IBM SPSS Categories)を使うことになります。

とは言え、Modelerでコレポンしたい!という気持ちもあります。

オープンソースでよければ、Pythonのmcaパッケージで多重コレスポンデンス分析ができます。

そこで、今回はModelerの拡張ノードを使って、多重コレスポンデンス分析をしてみます。

※Pythonでのコレポンはこちらの記事で紹介しています

分析テーマ例

飲料メーカーの商品イメージについてアンケート調査した結果から、商品とイメージのポジショニングを把握し、新規商品開発に役立てます。

実行環境

  • IBM SPSS Modeler Client 18.3
  • Python 3.8.6 ※Modeler同梱

作業ポイント

最初は拡張出力ノードを使ってみたのですが、Pythonのグラフ表示機能に対応していないようで、ポジショニング・マップを表示できませんでした。
そこで、拡張変換ノードでPythonのコレスポンデンス分析を行い、第1・2主成分のスコアを取得してから、散布図ノードでグラフを作ってみます。

  1. クロス集計表の読み込み
  2. 拡張変換ノードでコレスポンデンス分析
  3. ポジショニング・マップ(散布図)の作成

手順

1.mcaパッケージをインストール

Modelerで使用するPythonの指定方法やパッケージのインストール方法は、以下の記事をご参照ください。

2.クロス集計表を読み込む

今回はcsvファイルを使いますので、Modelerの[入力]パレットから「可変長ファイル」ノードを使用します。

ファイルには、以下のサンプルデータが含まれています。※手作りデータです
10商品(行)に対して、11のイメージ(列)があります。
アンケートで、各商品にそれぞれのイメージが当てはまるかどうか回答(Yes or No)してもらい、当てはまると回答された度数を集計したものです。

商品,高級感がある,お手頃価格,目が覚める,リラックスできる,よく飲む,たまに飲む,香り高い,あっさりしている,コクがある,渋みがある,おしゃれな感じ
エチオピア,22,28,36,46,5,4,26,13,6,3,7
カフェラテ,0,0,3,4,2,4,0,2,0,0,0
カプチーノ,7,11,17,23,4,5,2,4,3,2,5
グアテマラ,5,0,5,7,2,1,1,5,3,1,2
ココア,0,1,3,4,2,5,6,1,0,0,0
ブラジル,17,23,4,0,3,2,23,0,0,1,0
モカ,6,8,13,30,6,1,17,1,11,2,6
季節の果汁,5,7,16,23,2,2,5,6,5,3,5
煎茶,6,1,8,6,2,1,13,26,16,28,2
抹茶ラテ,27,13,16,2,2,12,0,2,1,2,10


3.拡張変換ノードを接続

[レコード設定]パレットから「拡張の変換」ノードを選択し、先ほどの「可変長ファイル」ノードから繋ぎます。

4.「拡張の変換」ノードを開き、「Python for Spark」を選択

5.「Pythonシンタックス」に下記を記述

#ライブラリのインポート
import mca  #コレスポンデンス分析
import numpy as np
import pandas as pd

#Modeler用
import spss.pyspark.runtime
from pyspark.sql.types import *

asContext = spss.pyspark.runtime.getContext()
sparkContext = asContext.getSparkContext()
sqlContext = asContext.getSparkSQLContext()

#データの読み込み
inputData = asContext.getSparkInputData()  #前ノードからのデータ読込
pdf = inputData.select("*").toPandas()  #pandasデータフレームワークに変換
indnm = pdf.columns[0]  #1列目の列名(商品)を取得
df = pdf.set_index(indnm)  #1列目の値(商品名)をインデックスに設定

#多重コレスポンデンス分析を実行
mca_counts = mca.MCA(df)
rows = mca_counts.fs_r(N=2)  #商品(行)の成分スコア Nは保持する成分の数
cols = mca_counts.fs_c(N=2)  #イメージ(列)の成分スコア Nは保持する成分の数

#商品(行)の成分スコアでデータフレームを作成
df_rows= pd.DataFrame(
    rows,
    columns = ['第1成分','第2成分']
)
rownm = df.index
df_rows.insert(0, 'クロス集計', '行')  #グラフプロット時に形状を指定するために使用
df_rows.insert(1, '対象', rownm)  

#イメージ(列)の成分スコアでデータフレームを作成
df_cols= pd.DataFrame(
    cols,
    columns=['第1成分','第2成分']
)
colnm = df.columns
df_cols.insert(0, 'クロス集計', '列')  #グラフプロット時に形状を指定するために使用
df_cols.insert(1, '対象', colnm)

#上記2つのデータフレームを結合
dfall = pd.concat([df_rows, df_cols])

#スキーマを作成(後続ノードに渡すフィールド(カラム)を設定)
fieldList =[
    StructField('クロス集計',StringType(),True),
    StructField('対象',StringType(),True),
    StructField('第1成分',FloatType(),True),
    StructField('第2成分',FloatType(),True)
]
outputSchema = StructType(fieldList)

#Modelerで使用 後続ノードに渡すデータ
if asContext.isComputeDataModelOnly():   
        outputData = sqlContext.createDataFrame(dfall)
        asContext.setSparkOutputSchema(outputSchema)
else:   
        outputData = sqlContext.createDataFrame(dfall)
        asContext.setSparkOutputData(outputData)

6.散布図ノードを接続

[グラフ]パレットから「散布図」ノードを選択し、「拡張の変換」ノードから繋ぎます。

7.散布図を作成

以下のように設定し、[実行]をクリックします。

  • Xフィールド:第1成分
  • Yフィールド:第2成分
  • 色:対象
  • 形状:クロス集計

下図のようなグラフが表示されます。※編集後のグラフです

こちらはModelerのグラフを[編集モード]で加工したもので、背景、フォント、枠線の変更や、凡例内の並べ替えなどを行いました。
Modelerのグラフは、デフォルトだとかなりクラシックな感じがする、と個人的には思います。
しかし、グラフの機能は豊富で、スタイルを変更したり、自分で編集した設定内容をノードに保存したり、デフォルトとして適用することもできます。
報告書の作成にも便利ですので、ぜひお試しください。

プロットされているものの名前とスコアは、マウスオーバーすると表示されます。

以上、Modelerで多重コレスポンデンス分析をしてみました。
※データの検定や結果の解釈などは省略

注意・改善ポイント

  1. スキーマでのデータ型の都合上、小数点以下が第4位に丸められてしまいます…
    が、ポジショニング・マップで全体を把握できれば良いかな、と思います。
  2. グラフ上に全部の名前を表示できると嬉しいのですが…
    Modelerの散布図ではできないようです。
    また、拡張ノードでPythonのグラフも使えません。
    拡張ノードのRスクリプトではグラフが表示できるようなので、Rでコレポンにチャレンジしてもよいかもしれません。

※参考

Python for Spark を使用したスクリプト – IBM Documentation
データのメタデータ – IBM Documentation
スクリプト例 – IBM Documentation
PySpark と pandas DataFrame 間の変換を最適化する
http://mogile.web.fc2.com/spark/sql-ref-datatypes.html