##スーパーノードとPythonスクリプト
SPSS Modelerで長いストリームを整理する(見やすくする)のに、スーパーノードを利用することがよくありますが、Pythonスクリプトでノードの設定を変更するときに、スーパーノード内のノードを扱う方法がわからず調査しました。
(スーパーノードを展開してしまえば解決しますが、この時はスーパーノードの数が多くて、できればスクリプトで解決したかったのです。)
備忘録も兼ねてその実現方法を残しておきます。
##まずはマニュアル
結論からいうと、そのやり方はマニュアルにしっかりと載っており、すぐに見つかりました。
IBM SPSS Modeler 18.2 Python スクリプトとオートメーション・ガイド
P.383 抜粋
カプセル化ノードのプロパティー設定
スーパーノード内の子ダイアグラムにアクセスすることにより、スーパーノードの中にカプセル化された特定のノードのプロパティーを設定できます。例えば、データを読み込むためにカプセル化された可変長ファイルのある入力スーパーノードがあるとします。以下のようにして、子ダイアグラムにアクセスし、関連ノードを検索することにより、読み込みファイルの名前 (full_filename プロパティーを使用して指定) を渡すことができます。
childDiagram = source_supernode.getChildDiagram()
varfilenode = childDiagram.findByType("variablefile", None)
varfilenode.setPropertyValue("full_filename", "c:/mydata.txt")
##実践編
上のマニュアルだけ見てさらっと理解できてしまう人は、もうこの先は読まなくても大丈夫です。もう少し具体的に知りたい方はもう少しお付き合いください。
###例題ストリーム
①購買履歴データから、RFM集計する、こんなストリームがあって
<img width="300" alt="WS0057.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361272/85ea0092-1ffd-9966-6a51-efdfaab41b8e.jpeg">
②スーパーノード(①の☆型ノード)の中身がこんなんだとします。
<img width="900" alt="WS0058.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361272/0cf2ef31-2c6b-8da5-9668-c8083723020c.jpeg">
スーパーノード内の"RECENCY"となっているフィールド作成ノードの中身は今こうなってます。
<img width="600" alt="WS0061.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361272/b78affdd-74af-886d-6d15-906c24352bf3.jpeg">
やってることは、最新の購入日が、2020/10/1を基準に何日前かを計算しています。
(SDATEが購入日。SDATE_Maxは事前の集計ノードで顧客毎の最新購入日になってると思ってください。)
ここで、基準日の2020/10/1を、ストリームの実行タイミングによって変更したい、例えばいつ実行しても直前の日曜日を基準に集計したい、などの要望があったとします。
その場合、Pythonスクリプトで datetime_date(2020, 10, 1) の部分を、基準としたい適切な日付に変えればいいのですが、スーパーノード内のノードは直接 findByXXXX() で扱えないので、先ほどのマニュアルで見た一手間が必要になります。
以下、Pythonスクリプトの例です。
import datetime
stream = modeler.script.stream()
基準日設定
RefDate = datetime.date(2020, 10, 10)
ストリーム内のスーパーノードを特定
rfm_process_super_node = stream.findByType("process_super", u"RFM集計")
スーパーノード内に展開されるダイアグラム(ストリームの事?)をインスタンス化
rfm_child_diagram = rfm_process_super_node.getChildDiagram()
スーパーノード内のフィールド作成ノードを特定
rfm_derive_node = rfm_child_diagram.findByType("derive", u"RECENCY")
特定したフィールド作成ノードに対して基準日を変更
rfm_derive_node.setPropertyValue("formula_expr", u"date_days_difference(SDATE_Max,datetime_date(" + str(RefDate.year) + "," + str(RefDate.month) + "," + str(RefDate.day) + ")")
"stream"が、①のストリーム、"rfm_child_diagram"が②のスーパーノード内のストリームだと理解すれば少しわかりやすいと思います。
<img width="600" alt="WS0068.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361272/0df2bdf2-47fb-f1e3-80ef-984a691e68cc.jpeg">
このスクリプトをストリーム内に仕込ん(ツール ⇒ ストリームのプロパティー ⇒ 実行)で実行すれば、基準日が2020/10/10にかわります。今回は簡略して基準日を指定してしまいましたが、基準日をどうするかのロジックは要件に合わせて考えてください。
下は、スクリプトを流して変更されたノードの設定です。うまくいきました。
(決して手で書き換えたわけではありません!)
<img width="600" alt="WS0062.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361272/1aef661a-afdc-cf5d-f68c-8b9f7b988528.jpeg">
※「こんな短いストリームなら、わざわざスーパーノードにしなくてもいいんじゃない?」などの突っ込みはどうかご遠慮ください。
##試した環境
Modeler 18.2.1
Windows 10