SPSS Modelerのフィールド順序ノードをPythonで書き換える。


SPSS Modelerで列の順序を変えるのがフィールド順序ノードです。
これをPythonのpandasで書き換えてみます。


#0．元データ
以下の時系列のセンサーデータをつかって行います。

■COND2n.csv
Time:稼働時間
Power:電力
Temperature:温度
Pressure:圧力
Uptime:起動時間
Status:状態コード
Outcome:エラーコード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/f36120bb-57d1-34ae-92af-07a080085277.png)


#1m．フィールド順序変更　Modeler版

「COND2n.csv」の列順序を
Time,Power,Temperature,Pressure,Uptime,Status,Outcome
の順序から
Time,Uptime,Power,Temperature,Pressure,Outcome,Status
に変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/48c90cdf-03e8-6d37-df2a-e757cbcf8876.png)

フィールド順序で、Time,Uptimeを選び、上から２つにセットします。
次にOutcome,Statusを下から２つにセットします。

ポイントは「-----[他のフィールド]------」という項目があり、他のフィールドは元表での列順序を保ったまま自動的に配置されることです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/e1809fda-9da1-7c1a-a024-ee6e612c1bb8.png)


Power,Temperature,Pressureのような同種類のデータをセットとして扱いたい場合によく使います。今回は3列しかありませんが、大量に列があるときには、全ての列を1列、1列指定しなくてよいのでとても便利です。また、センサーについての列が追加された場合も修正の必要がありません。


#1p．フィールド順序変更　pandas版

方法はいくつかあり得ます。
1番目の単純な方法は変更後の全列のリストを与える方法です。

```python
#列を入れ替える１：すべての列を記載する
df1_1=df1[['Time','Uptime','Power','Temperature','Pressure','Outcome','Status']]
df1_1
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/2a6143fd-2a32-905c-38b0-47bb271fe2c5.png)

しかし、この方法は列がたくさんある場合は大変な方法になりますし、可読性も下がります。Modelerのように一部の列をセットとして扱う方法を検討します。

2番目の方法はdataframeを3つのパートに分ける方法です。
ポイントはdf1.loc[:,'Power':'Pressure']で、'Power','Temperature','Pressure'の３列分のdataframeを作っていることです。

```python
#列を入れ替える２：3つのDFを作って連結する
df1_2=pd.concat([df1[['Time','Uptime']],
                 df1.loc[:,'Power':'Pressure'],
                 df1[['Outcome','Status']]], axis=1, join='inner')
df1_2
```
しかし、この方法は中間的にdataframeをたくさん作っていて、データの件数が多い時にはかなり非効率だと思います。

3番目の方法は
columns.tolist()でカラム名のリストをつくってから
collist[collist.index('Power'):collist.index('Pressure')+1]で「'Power','Temperature','Pressure'」の列名のリストを作っています。

```python
#列を入れ替える３：列のリストオブジェクトを作る
collist=df1.columns.tolist()

df1_3=df1[['Time', 'Uptime']+
          collist[collist.index('Power'):collist.index('Pressure')+1]+
          ['Outcome','Status']]
df1_3
```
2番目の方法よりこの方法が軽くはなっています。ただ、可読性はあまり高くないプログラムです。

4番目の方法は、2番目と3番目の方法を組み合わせたものです。
df1.loc[0:0,'Power':'Pressure']で'Power',1レコードだけの'Temperature','Pressure'だけのdataframeをつくって、columns.tolist()でカラムのリストだけを取り出しています。

```python
#列を入れ替える4：切り出したDFから列のリストオブジェクトを作る
collist= df1.loc[0:0,'Power':'Pressure'].columns.tolist()

df1_3=df1[['Time', 'Uptime']+
          collist+
          ['Outcome','Status']]
df1_3
```

まだあまり可読性が高いとは言えませんが、2番目の方法より軽く、3番目の方法よりは読みやすいかと思います。

* 参考
 * pandas.DataFrame, Seriesの重複した行を抽出・削除 | note.nkmk.me 
 * https://note.nkmk.me/python-pandas-duplicated-drop-duplicates/
 * pandas.DataFrame.append — pandas 1.1.4 documentation
 * https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.append.html#pandas.DataFrame.append

#2. サンプル
サンプルは以下に置きました。

ストリーム
https://github.com/hkwd/200611Modeler2Python/raw/master/fieldreorder/fieldreorder.str
notebook
https://github.com/hkwd/200611Modeler2Python/blob/master/fieldreorder/fieldreorder.ipynb

データ
https://raw.githubusercontent.com/hkwd/200611Modeler2Python/master/data/COND2n.csv

■テスト環境
Modeler 18.2.2
Windows 10 64bit
Python 3.7.9
pandas 1.0.5

#3. 参考情報

フィールド順序ノード
https://www.ibm.com/support/knowledgecenter/ja/SS3RA7_18.2.2/modeler_mainhelp_client_ddita/clementine/reorder_overview.html