SPSS Modelerのデフォルトディレクトリの使い方とデータへのファイルパス違いの対応方法

SPSS Modelerで他の人からもらったストリームを実行するときにデータへのファイルパスが違って実行ができないことがあると思います。デフォルト・ディレクトリの設定をつかってファイルパスを手で修正しないで実行する方法を紹介します。

作ったbatやpythonスクリプト、サンプルストリームは以下に置きました。

https://github.com/hkwd/spssmodelerscript/tree/master/210430defaultdirectory

■テストした環境
Modeler 18.2.2
Windows 10

#1.デフォルトディレクトリ

SPSS Modelerの可変長ファイルなどの入力ノードを読むときのデフォルトのディレクトリが設定されています。デフォルトの設定は、WindowsではC:\ProgramDataです。しかしながら、このフォルダにデータを置く人はあまりいないと思うので不便だと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/4e39932d-33bd-2e1a-a66c-b804cad04c12.png)

これをModelerのメニューから変える場合は、ファイルのディレクトリの設定を選びます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/18de526a-c6e2-9545-ee0d-94f087f6ea9a.png)


例えば、自分のドキュメントフォルダなどに設定しておくのが使いやすいかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/08c227cc-c959-ca5c-741d-3e2f53c4283e.png)

設定をしておくと、可変長ファイルなどの入力ノードでデータを探す起点が変更できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/b1cd9523-1b71-73bd-641e-c9c2becbdc2c.png)


また、パスの指定をデフォルトパスからの相対パスで指定ができます。
通常は以下の「C:\Users\dsuser01\Documents\テスト\iris.csv」というような絶対パスです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/7d778594-01b2-b2c2-0415-46b1ffd3a4bc.png)

しかしながら、以下のように「テスト\iris.csv」のような相対パスで指定が可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/61c0f56a-2829-e980-43c1-59edfd7dd9c1.png)




なお、一度設定したデフォルト・ディレクトリは
C:\Users\<ユーザー名>\AppData\Roaming\IBM\SPSS\Modeler\18.2.2\Defaults\session.prefsに保存されますので次回起動した際にも有効になります。

```
# 2021-04-30 01:18:21-0500
DefaultWorkingDirectories=C\:\\Users\\dsuser01\\Documents
```

#2. デフォルトディレクトリを簡単に設定する
相対パスで指定しておくと、他の人が同じデータとストリームを別のマシンで実行する場合に、絶対パスが完全に揃っていなくても参照が可能です。
特にファイル名だけの指定になっていると、フォルダの構成の全く異なる他の人のマシンでもパスを書き換えなくてもすぐにストリームを動作させることができます。
しかしながら、デフォルトディレクトリをいちいち変更するのは結構面倒です。

そこで以下のようなバッチファイルを作りました。

```bat:modelercur.bat
@echo off
setlocal
SET MODELERPATH="C:\Program Files\IBM\SPSS\Modeler\18.2.2\bin\modelerclient.exe"

REM カレントディレクトリの取得
for /f "usebackq delims=" %%A in (`CHDIR`) do set CDIR=%%A
echo %CDIR%
echo %1\
REM 引数がフォルダであることを判定
for /f "usebackq delims=" %%A in (`powershell Test-Path -PathType container %1`) do set CONTAINTER=%%A
echo %CONTAINTER%

if  %CONTAINTER%==True (
  echo "direcotry"
  REM 引数をデフォルトディレクトリとしてModelerを起動
  start "" %MODELERPATH% -directory "%1"
) else (
  echo "file"
  REM カレントディレクトリをデフォルトディレクトリとしてModelerを起動。引数のstrファイルを開く
  start "" %MODELERPATH% -directory "%CDIR%" -stream "%1"
) 
```

SET MODELERPATH="C:\Program Files\IBM\SPSS\Modeler\18.2.2\bin\modelerclient.exe"はお使いのmodelerclient.exeのパスを指定してください。

このファイルをC:\Users\＜ユーザー名＞\AppData\Roaming\Microsoft\Windows\SendToに保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/dd388434-4bc0-a034-55a3-efc58e37e8a6.png)


そして開きたいstrファイルを選んで、右クリックの送るからmodelercur.batを選びます。
ここではC:\Users\dsuser01\Documents\テストのtest.strを開いています。データは同じフォルダのiris.csvに置いてあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/7aa36d1a-9656-082f-8372-1a5b6e51a05a.png)

起動したModelerのデフォルトディレクトリの設定を見るとC:\Users\dsuser01\Documents\テストになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/e4be91bc-4b70-dc6d-4291-b36ca6585111.png)

ですので、ファイル名だけでデータが参照できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/cdcf1ced-fbce-57b7-68a9-1b038fd724d2.png)



また、strファイルではなく、フォルダを選んで右クリックの送るからmodelercur.batを選んだ場合は、そのフォルダがデフォルトディレクトリとしてセットされてModelerが起動します。
ここではC:\Users\dsuser01\Documents\テスト２を選んでいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/5d519e7b-39cf-3c74-a481-c9c8039261d5.png)

起動したModelerのデフォルトディレクトリの設定を見るとC:\Users\dsuser01\Documents\テスト２になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/7e0b9f36-e6e3-0449-39a2-cc26a61fe336.png)


#３．既存ストリームの絶対パスを相対パスに置き換える。
デフォルトディレクトリさえ設定してあれば、他の人からもらったstrファイルやエクスポートノードのパスを相対パスに変えてしまえば、すぐに開いてみることができます。

これを、以前書いたファイルパスを一括変換するmodelerスクリプトを修正して作りました。

https://qiita.com/kawada2017/items/5db798b8becbf3e75f2b　

```python:changecurrelpath.py
import modeler.api
import os

for stream in modeler.script.streams():
    print("stream:"+stream.getName().encode('utf-8'))
    #streamfilenpath=stream.getLastSavedAs()
    #newpath=os.path.dirname(streamfilenpath)

    #session=modeler.script.session()
    #newpath=session.getDefaultDataDirectory()
    #print("newpath:"+newpath.encode('utf-8'))

    for node in stream.iterator():
        if (node.getTypeName() == "variablefile"
            or node.getTypeName() == "excelimport"
            or node.getTypeName() == "statisticsimport"
            or node.getTypeName() == "outputfile"
            or node.getTypeName() == "excelexport"
            or node.getTypeName() == "statisticsexport"):
            full_filename=node.getPropertyValue("full_filename")
            print("old:"+full_filename.encode('utf-8'))
            #full_filename=newpath+"\\"+os.path.basename(full_filename)
            full_filename=os.path.basename(full_filename)
            print("new:"+full_filename.encode('utf-8'))
            node.setPropertyValue("full_filename",full_filename)
```

新規のファイル名をos.path.basename(full_filename)でファイル名だけにしています。


テスト実行してみます。
以下のストリームでは入力ノードのファイルがC:\Users\dsuser01\Documents\テスト\iris.csvのように絶対パスで設定されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/15492bbe-f07b-e445-b936-b676bbcee770.png)

ツールのメニューからスタンドアロンスクリプトを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/32ea475a-a3bd-d0d6-953b-9225777b6eab.png)

changecurrelpath.pyのpythonスクリプトを貼付け、実行します。デバッグを見ると変換の行われた入力が出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/82749b1d-a584-3420-0047-27670ad99a59.png)

ファイル名が相対パスのファイル名だけに変換されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/b622fedf-0cbd-7afb-36d1-dcbfc2e22175.png)


なお、閉じるときにスタンドアロンスクリプトを保存するかを聞かれますが、保存する必要はありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/58939ae4-b191-7fc0-482a-637b688a2317.png)


#4. 相対パス変換までの自動化
さらに、２．デフォルトディレクトリを簡単に設定するバッチをもう少し変更して、３のchangecurrelpath.pyを自動的に実行するようにしてみます。

まず、changecurrelpath.pyをC:\Users\＜ユーザー名＞\AppData\Roaming\Microsoft\Windows\SendToに保存します。

そして以下のバッチファイルも作り、同じくC:\Users\＜ユーザー名＞\AppData\Roaming\Microsoft\Windows\SendToに保存します。

```bat:modelercurreplace.bat
@echo off
setlocal
SET MODELERPATH="C:\Program Files\IBM\SPSS\Modeler\18.2.2\bin\modelerclient.exe"
SET MODELERSCRIPT="%AppData%\Microsoft\Windows\SendTo\changecurrelpath.py"

REM カレントディレクトリの取得
for /f "usebackq delims=" %%A in (`CHDIR`) do set CDIR=%%A
echo %CDIR%
echo %1\
REM 引数がフォルダであることを判定
for /f "usebackq delims=" %%A in (`powershell Test-Path -PathType container %1`) do set CONTAINTER=%%A
echo %CONTAINTER%

if  %CONTAINTER%==True (
  echo "direcotry"
  REM 引数をデフォルトディレクトリとしてModelerを起動
  start "" %MODELERPATH% -directory "%1"
) else (
  echo "file"
  REM カレントディレクトリをデフォルトディレクトリとしてModelerを起動。引数のstrファイルを開き相対パスに書き換えるスクリプトを実行する
  start "" %MODELERPATH% -directory "%CDIR%" -stream "%1" -script "%MODELERSCRIPT%" -execute
)

```

先ほどとの違いは、カレントディレクトリをデフォルトディレクトリに設定してstrファイルを開くだけではなく、スタンドアロンスクリプトとして、changecurrelpath.pyを実行して、すべてのパスを相対パスに置き換えていることです。

```bat
start "" %MODELERPATH% -directory "%CDIR%" -stream "%1" -script "%MODELERSCRIPT%" -execute
```

以下のようにSendToの下に保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/b313e908-b19e-4f30-3fc5-555f04c8933c.png)


テスト実行してみます。
相対パスに書き換えたいstrファイルを選び、右クリックの送るからmodelercurreplace.batを選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/456e24c5-7898-822d-ca0f-826b3e3c5c02.png)

カレントディレクトリをデフォルトディレクトリとしてModelerが起動し、strファイル内の入力ノードの絶対パスが相対パスに書き換わりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/f1dc32b5-65a4-da9c-b6a2-71614a3d51d2.png)

これでstrファイルとデータファイルを同じフォルダに入れておけば、手でパスを修正しなくても動かすことができます。