【SPSS】Modelerの拡張機能でカスタムノードを作成する方法 ~BigQueryインポート~

【SPSS】Modelerの拡張機能でカスタムノードを作成する方法 ~BigQueryインポート~

IBM SPSS Modelerには、自分でノードを作成できる機能があります。

「カスタム ノード ダイアログ ビルダー」を使って、カスタム・ノード・ダイアログ(ノードを開いた時の設定画面)を作成し、PythonまたはRのスクリプトを実行するノードを作成できます。

PythonやRで作成したスクリプト拡張ノードを使いまわしたり、コーディングが苦手な分析メンバーと共有する場合などに便利です。

標準搭載されているノードと同様、必要な項目だけを設定するように作れるため、コーディングミスの防止にも役立ちます。

ノードのアイコンも自由に設定できるため、会社のロゴやチームメンバーの顔、ペットの写真などをノードにしても楽しいです(笑)

今回は、Python スクリプトを使って、BigQueryからデータをインポートするカスタムノードを作ってみます。

色々な機能を付けたくなりますが、まずはシンプルなノード(下図)にします。

作業ポイント

  1. 「ダイアログ プロパティ」を設定
  2. 「ツール」を設置&設定
  3. 「スクリプト」(Python for Spark)を記入してコントロール識別子を挿入
  4. 「拡張プロパティ」を設定
  5. 「インストール」を実行

実行環境

  • IBM SPSS Modeler Client 18.3
  • Python 3.8.9

準備

こちらの「準備」をご参照ください。

手順
1.基本編

1.Modelerのメニューバーにある [拡張機能]>[カスタム ノード ダイアログ ビルダー]を選択

カスタム ダイアログ ビルダーが開きます。
下図の①~⑦の順で作業するイメージです。

2.「ダイアログ プロパティ」を設定

ノードの概要を決めます。
今回は、以下の3つを設定します。

  • 表題:BQインポート
  • スクリプトタイプ:Spark用Python
  • ノードタイプ:インポート ※「パレット」が自動的に「ソース」になります

ちなみに、「ノードアイコン」に画像ファイルを選択すると、見た目もオリジナルなノードになります。
画像サイズがそのまま適用されるため、大きさには要注意です。
指定がない場合は、デフォルトのアイコンが使われます。

3.「ツール」を設置&設定

3-1.SQL文

SQL文を入力する部分を作成します。
使用するツールは「静的テキスト」と「テキスト コントロール」です。

3-1-1.静的テキスト

静的テキストとは、入力欄の説明など、ノード上で表示させるだけで変更できないテキストです。
[ツール]から「静的テキスト」を選択し、[モデルオプション]にドラッグ&ドロップします。

テキストの編集は、[静的テキスト プロパティ]で行います。
[表題]に「SQL文」と入力します。

3-1-2.テキスト コントロール

テキストコントロールは、ノードに手入力できる欄を作れます。
[ツール]から「テキストコントロール」を選択し、[モデルオプション]にドラッグ&ドロップします。
プロパティでは、[引用符の処理]に「Python」を選択します。
また、[デフォルト値]は無くても構いませんが、「SELECT * FROM」としておきます。

3-2.認証用ファイル

続いて、認証用ファイルの入力部分を作成します。

3-2-1.静的テキスト

[ツール]から「静的テキスト」を選択し、[モデルオプション]にドラッグ&ドロップします。
[静的テキスト プロパティ]の[表題]に、「BigQuery認証用jsonファイルパス」と入力します。
表題の文字数が多い場合、表示が切れて見えるのですが、実際にはきちんと表示されます。

ノード上での表示は、[プレビュー]で確認できます。
[プレビュー]をクリックすると・・・

全文表示されていることが確認できました。

3-2-2.テキスト コントロール

[ツール]から「テキストコントロール」を選択し、[モデルオプション]にドラッグ&ドロップします。
プロパティでは、[引用符の処理]に「Python」を選択します。
また、入力必須な項目とするため、[実行に必要]を「True」にします。
応用編で、ファイルブラウザを使用する方法もあります。

3-3.アウトプットスキーマ

同様に、アウトプットスキーマの入力部分を作成します。

3-3-1.静的テキスト

[ツール]から「静的テキスト」を選択し、[モデルオプション]にドラッグ&ドロップします。
[静的テキスト プロパティ]の[表題]に、「アウトプットスキーマ」と入力します。

3-3-2.テキスト コントロール

[ツール]から「テキストコントロール」を選択し、[モデルオプション]にドラッグ&ドロップします。
プロパティでは、[引用符の処理]に「Python」を選択します。
また、入力必須な項目とするため、[実行に必要]を「True」にします。


ここまでの作業で、外側ができました。
次に、中身を詰めていきます。

4.「スクリプト」を記入してコントロール識別子を挿入

下図の④のエリアにスクリプトを記入し、⑤のエリアから識別子を選択して挿入していきます。

4-1.スクリプト

以下の記事で紹介したスクリプトを基に、一部変更して使います。
Python スクリプトの場合は、データが Spark DataFrame 形式で表示されるため、Spark API を使用する必要があります。
※拡張ノードで実行できたスクリプトをコピペして、必要箇所のみをコントロール識別子に置き換えると間違えにくいと思います。

今回使用するスクリプトは、こちらです。

#Modelerで使用
import spss.pyspark.runtime
from pyspark.sql.types import *
asContext = spss.pyspark.runtime.getContext()
sqlContext = asContext.getSparkSQLContext()

#BigQueryで使用
from google.cloud import bigquery
import os
import pandas
import pyarrow

#アウトプットスキーマを作成(後続ノードに渡すフィールド(カラム)を設定)
fieldList =[
    StructField('AAAAAAAAAA',IntegerType(),True),
    StructField('BBBBBBBBBB',StringType(),True)
]
outputSchema = StructType(fieldList)

#BigQuery認証用jsonファイルを指定(ローカルに保存)※Windowsの場合は「r'%%item_13%%'」
credentials_json = './XXXXX.json'

#BigQuery環境変数
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = credentials_json

#Modelerで使用
asContext.setSparkOutputSchema(outputSchema)
if not asContext.isComputeDataModelOnly():

    #BigQuery接続用
    bigquery_client = bigquery.Client()
    #SQL文
    query = 'SELECT AAAAAAAAAA,BBBBBBBBBB FROM `{0}.{1}.{2}`'.format(project, dataset, table)
    
    df = bigquery_client.query(query).to_dataframe()
    #Modelerで使用(後続ノードに結果を渡す)
    outputData = sqlContext.createDataFrame(df)
    asContext.setSparkOutputData(outputData)


4-2.コントロール識別子

上記スクリプトの3箇所を識別子コントロール識別子)に置換します。
コントロールとスクリプトで項目の順番が違うので要注意です。
識別子を選択すると、[モデルオプション]で該当コントロールがハイライトされるので、確認しながら作業すると良いと思います。
ちなみに、ここでの識別子は以下の通りです。

  • item_5:SQL文
  • item_13:BigQuery認証用jsonファイルパス
  • item_15:アウトプットスキーマ


まずは、アウトプットスキーマ部分(下図15,16行目)を選択し、識別子を右クリックして[スクリプト テンプレートに追加]を選択します。
もちろん、手入力で書き換え(%%識別子%%)てもOKです。

前後に「%%」がついた識別子に置換されました。

同様に、下図のように認証用ファイルとSQL文も置換します。
※Windowsの場合は「’r%%item_13%%’」

置換後は以下のようになります。

#Modelerで使用
import spss.pyspark.runtime
from pyspark.sql.types import *
asContext = spss.pyspark.runtime.getContext()
sqlContext = asContext.getSparkSQLContext()

#BigQueryで使用
from google.cloud import bigquery
import os
import pandas
import pyarrow

#アウトプットスキーマを作成(後続ノードに渡すフィールド(カラム)を設定)
fieldList =[
%%item_15%%
]
outputSchema = StructType(fieldList)

#BigQuery認証用jsonファイルを指定(ローカルに保存)※Windowsの場合は「r'%%item_13%%'」
credentials_json = '%%item_13%%'

#BigQuery環境変数
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = credentials_json

#Modelerで使用
asContext.setSparkOutputSchema(outputSchema)
if not asContext.isComputeDataModelOnly():

    #BigQuery接続用
    bigquery_client = bigquery.Client()
    #SQL文
    query = '%%item_5%%'
    
    df = bigquery_client.query(query).to_dataframe()
    #Modelerで使用(後続ノードに結果を渡す)
    outputData = sqlContext.createDataFrame(df)
    asContext.setSparkOutputData(outputData)

6.「拡張プロパティ」を設定

「拡張プロパティ」が設定されていないと、ノードが作成されません。
上書き保存もできませんのでお忘れなく!
メニューがわかりにくいのですが、[拡張機能]から「プロパティ」を選択します。

ここでは下記のように設定します

  • 名前:BQインポート
  • 要約:ここも入力が必要 (もう少し気の利いた例にすればよかったですね・・・)
  • ファイル:ダイアログ435.cfe

「名前」はノード名になります。
「要約」も入力必須です。
「ファイル」は今回作成しているダイアログ名(手順2のダイアログ名)がデフォルトで選択されています。

入力し終えたら、[続行]をクリックします。

7.上書き保存して「インストール」を実行

最後のプロセスです。
[上書き保存]し、[インストール]をクリックします。

インストール完了メッセージが表示されます。

8.作成したノードを確認

[入力]パレットに[BQインポート]ノードが追加されています。

ノードを開いて確認します。
SQL文にデフォルト値が入っており、入力必須に設定した欄は、「値を入力してください」と表示されます。
※全部に表示されると鬱陶しく見えるので、ユーザーが忘れやすそうな項目だけにした方が良いと思います。

基本編は以上です。

2.応用編

ファイルパスの指定には、ファイルブラウザを使うこともできます。

[ツール]から「ファイル ブラウザ」を選択し、[モデルオプション]にドラッグ&ドロップします。
プロパティでは、[ファイル システム操作]を「開く」、[ファイル システムの種類]を「クライアント」に設定します。

<余談>
テキスト コントロールでは、複数行表示になると自動で縦幅が調整されます。
改行を含むテキストをコピペすると改行されているように見えるのですが、
下矢印でカーソルが動かないので、行が折り返されているだけでしょうか??
手入力でも改行できませんでした。

アウトプットスキーマの入力方法は、もっと工夫できるのではないかと思いますが、今回はここまでにしておきます。

※参考
https://www.ibm.com/docs/ja/spss-modeler/18.3.0?topic=extensions-creating-managing-custom-nodes