SPSS Modelerの文字列に関するCLEM関数をPythonで書き換える

以下の記事を参照しつつ、SPSS Modelerのclem関数を使って文字列型のレコードを加工してその処理をPythonで書き換えてみます。

https://qiita.com/Makimaki2020/items/35ab02a7375325e678c1

加工に使用するデータは、以下から取得しました。
・「データサイエンティスト協会スキル定義委員」の「データサイエンス100本ノック（構造化データ加工編）」https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess
・海外在留邦人数調査統計 https://www.e-stat.go.jp/stat-search/files?page=1&layout=datalist&toukei=00300100&tstat=000001055779&cycle=0&tclass1=000001116075&file_type=1&result_page=1&tclass2val=0

上記の記事で紹介されているとおり、文字列関数の実行結果は主に3種類です。
1. 文字列: String
2. 文字の位置: Integer ※
3. 真(1)偽(0): Boolean  (この記事では実行例割愛)
※SPSS Modelerの添え字が1から始まるのに対してPythonは0から始まるため注意が必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/a3e16395-c576-d497-a505-a4cfc1d02e84.png)

### 1. 結果を文字列で返す関数

#### 1. 部分文字列の抽出
##### 1. 先頭/末尾N文字
[実行例]
例1: 地域名の先頭のローマ数字のみ抽出
例2: 生年月日の日付のみ抽出
　　　※日付型としての処理については以下の記事を参照
　　　https://qiita.com/kawada2017/items/0546580314f5b67408b1
例3: コードの末尾1文字を抽出

◇ SPSS Modeler
    例1: startstring(_N_,'_<フィールド名>_')
    例2: endstring(_N_,to_string(_<フィールド名>_))
    例3: last(_<フィールド名>_)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/7712b795-19c7-a78b-508b-95b58d3a99bd.png)

◇ Python
    例1: _<データフレーム名>_['_<カラム名>_'].str[:_N_-1]
    例2: _<データフレーム名>_['_<カラム名>_'].str[-_N_:]
    例3: _<データフレーム名>_['_<カラム名>_'].str[:-1]

```
df_zairyu_houjin['region_cd'] = df_zairyu_houjin['地　域'].str[:1]
df_customer['day_of_birthday'] = pd.to_numeric(df_customer['birth_day'].str[-2:])
df_customer['status_last_char'] = df_customer['status_cd'].str[-1]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/fd8007d5-fd0e-1991-2efe-ecddc6d8238e.png)

##### 2. N番目の文字を抽出
[実行例]
例1: 年月日フィールドの年の末尾(4番目)の文字を抽出
例2: 店舗コードの各県ごとに採番されたID(4番目から3文字)を抽出
例3: 年月日フィールドの月(5,6番目)の文字を抽出
例4: '-'区切りのコードの2番目の部分文字列を抽出

◇ SPSS Modeler
    例1: subscrs(_N_,_<フィールド名>_)
    例2: substring(_N1(開始位置)_,_N2(終了位置)_, _<フィールド名>_))
    例3: substring_between(_N1(開始位置)_,_N2(終了位置)_,_<フィールド名>_)
    例4: textsplit(_<フィールド名>_,_N_,'_<区切り文字>_')
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/b4e52bc8-0f81-1df5-ea74-185f742af134.png)

◇ Python
   例1: _<データフレーム名>_['_<カラム名>_'].str[_N_]
   例2: _<データフレーム名>_['_<カラム名>_'].str[_N1_:_N2_]
   例3: _<データフレーム名>_['_<カラム名>_'].str[_N1_:_N2_]
   例4: _<データフレーム名>_['_<カラム名>_'].str.split('_<区切り文字>_',expand=True)

```
df_customer['application_year_last'] = df_customer['application_date'].astype(str).str[3]
df_store['store_num'] = df_store['store_cd'].str[3:6].astype(int)
df_customer['application_month'] = df_customer['application_date'].astype(str).str[4:6]
df_customer['status_mid'] = df_customer['status_cd'].str.split('-',expand=True)[1]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/4e2d849e-13ad-011f-7bd9-2a8909f6cda8.png)

#### 2. 部分文字列の削除

##### 1. 文字列の先頭/末尾のN字を削除
[実行例]
例1: 商品コード(product_cd)から接頭文字(P)を削除
例2: 店舗名(store_name)から「店」を削除

◇ SPSS Modeler
    例1: allbutfirst(N, _<フィールド名>_)
    例2: allbutlast(N, _<フィールド名>_)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/331b76a5-f6f8-c789-4652-2b33f7d712c4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/e657eb9c-ed6a-1a54-51d6-fb84910248fd.png)

◇ Python
    例1: _<データフレーム名>_['_<カラム名>_'].str[_N-1_:]
    例2: _<データフレーム名>_['_<カラム名>_'].str[:-_N_]

```
df_product['product_code_int'] = pd.to_numeric(df_product['product_cd'].str[1:])
df_store['store_without_ten'] = df_store['store_name'].str[:-1]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/2767fed4-5491-6760-bd48-692ef67bbc53.png)

##### 2. 先頭や末尾の空白文字を削除
[実行例]
    接頭辞を削除した地域名の空白文字を削除

◇ SPSS Modeler
    先頭の空白文字を削除: trimstart(_<フィールド名>_)
    末尾の空白文字を削除: trimend(_<フィールド名>_)
    先頭および末尾の空白文字を削除: trim(_<フィールド名>_)
    ※ 末尾の空白文字の削除例は割愛、今回の例では実行結果は先頭/先頭および末尾で同一のため先頭および末尾の例を記載
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/77f8f5d1-2acb-ee71-3878-646cc5414369.png)

◇ Python
    先頭の空白文字を削除: _<データフレーム名>_['_<カラム名>_']str.lstrip()
    末尾の空白文字を削除: _<データフレーム名>_['_<カラム名>_']str.rstrip()
    先頭および末尾の空白文字を削除: _<データフレーム名>_['_<カラム名>_']str.strip()

```
df_zairyu_houjin['region_name'] = df_zairyu_houjin['地\u3000域'].str[1:].str.lstrip()
df_zairyu_houjin['region_name'] = df_zairyu_houjin['地\u3000域'].str[1:].str.rstrip()
df_zairyu_houjin['region_name'] = df_zairyu_houjin['地\u3000域'].str[1:].str.strip()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/9ce958de-3422-1401-4e69-74cc08f93a38.png)

##### 3. 特定の文字列の削除
[実行例]
    文字列中の"E"をすべて削除

◇ SPSS Modeler
    stripchar(<_CHAR_>, _<フィールド名>_)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/e4282e16-d4f0-0fed-eabd-0766d0490eaf.png)

◇ Python

```
_<データフレーム名>_['_<カラム名>_']str.replace("_CHAR_","")
```
※Pythonのstrip系の関数の引数に文字列をとると先頭もしくは末尾から削除可能。ただし中間部の文字は削除できないためreplace関数を使用
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/ebd00b02-e899-54b1-a018-dd84ea0297cc.png)

#### 3. 文字列の置換
##### 1. 任意の文字列間の置換
[実行例]
    カテゴリー名を「惣菜」から「デリカ」へ置換

◇ SPSS Modeler
    replace('_<置換前文字列>_','_<置換後文字列>_',_<フィールド名>_)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/366e9d9b-12ff-38f2-dee6-b7e0bd52579e.png)

◇ Python
    df_category['new_cate'] = df_category['category_major_name'].str.replace('惣菜','デリカ')
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/5500e095-b4f9-83b0-c929-d951c6ad0982.png)


##### 2. 大文字/小文字変換
◇ SPSS Modeler
    大文字から小文字: uppertolower(_<フィールド名>_)
    小文字から大文字: lowertoupper(_<フィールド名>_)
    ※小文字から大文字への変換例は割愛
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/a678ea58-5010-4ab3-e1a3-a9fb80d029cb.png)

◇ Python
    大文字から小文字: _<データフレーム名>_['_<カラム名>_']str.lower()
    小文字から大文字: _<データフレーム名>_['_<カラム名>_']str.upper()
    ※小文字から大文字への変換例は割愛

```
df_sampletran['l_class_lower'] = df_sampletran['L_CLASS'].str.lower()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/02cadf80-a68b-cbff-fb9f-54b465ef88fb.png)

#### 4. その他の文字列を返す処理
##### 1. 指定文字列のN個のコピーからなる文字列
◇ SPSS Modeler
    replicate(_N_,'_<文字列>_')
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/913233f2-51c0-10b8-43a8-b75c413201dd.png)

◇ Python
    ['_<文字列>_' * N for i in _<データフレーム名>_.index]
　　データフレームに新しいカラムを追加し、インデックスの数だけ指定文字列を繰り返した値を挿入している

```
df_sampletran['repeat_times_by_index'] = ['abc' * (i + 1) for i in df_sampletran.index]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/e75fc1d5-d1d5-479a-d69e-6583552ed895.png)

##### 2. Unicode値から文字への変換
◇ SPSS Modeler
    unicode_char(_N_)
　　※10進数で入力する、16進数には対応していない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/56f41d53-57f4-d808-38ac-4f75840d705b.png)

◇ Python
    chr(_N_)

```
df_sampletran['unique_char_by_index'] = [chr(65+i) for i in df_sampletran.index]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/5a19143f-a6bf-6725-74f6-96bf609ddea0.png)

### 2. 結果を数値で返す関数
#### 1. 部分文字列の位置の取得
◇ SPSS Modeler
#####1. 部分文字列が値に含まれる場合に添え字を返す
issubstring('_<部分文字列>_', _<フィールド名>_)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/77562832-0472-68da-5d25-dcbd566eec36.png)

#####2. 部分文字列が値の先頭に含まれる場合に添え字を返す
isstartstring('_<部分文字列>_', _<フィールド名>_)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/9f501a63-b6f3-bd1f-1a07-d9295ab7cb40.png)

#####3. 部分文字列が値の中間に含まれる場合に添え字を返す
ismidstring('_<部分文字列>_', _<フィールド名>_)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/e9e064ca-5232-cbcd-96c6-8414214ed743.png)

#####4. 部分文字列が値の末尾にある場合に添え字を返す
isendstring('_<部分文字列>_',_<フィールド名>_)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/4e566bbf-546a-0b78-507e-8f433d23340a.png)

◇ Python
#####1. 部分文字列が値に含まれる場合に添え字を返す
_<データフレーム名>_['_<カラム名>_'].str.find('_<部分文字列>_') + 1

```
df_customer['dai_index'] = df_customer['customer_name'].str.find('大') + 1
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/0889263f-8c39-ab00-7a7f-0944692f60d9.png)

#####2. 部分文字列が値の先頭に含まれる場合に添え字を返す
_<データフレーム名>_['_<カラム名>_'].str.startswith('_<部分文字列>_') * 1
※startswithで審議値を取得し"*1"で数値に変換

```
df_customer['tomin_flg'] = df_customer['address'].str.startswith('東京都') * 1
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/6ad4c8ad-f40f-56be-453f-fc48550fe80a.png)

#####3. 部分文字列が値の中間に含まれる場合に添え字を返す
 [_<データフレーム名>_['_<カラム名>_'][i].find('_<部分文字列>_')+1 if _<データフレーム名>_[1:-1].find('_<部分文字列>_') != -1 else 0 for i in range(len(_<データフレーム名>_))]
※値の先頭と末尾から1文字削除した後で部分文字列が含まれる場合は添え字+1を返している 例: 値が"abcdcba"で部分文字列が"bc"の場合先頭と末尾から1文字を削除した"bcdcba"に"bc"が含まれるため"abcdcba"中の"bc"の添え字+1である2を返す

```
df_customer['mid_ta_index'] = [df_customer['customer_name'][i].find(substr)+1 if df_customer['customer_name'][i][len(substr):-len(substr)].find(substr) != -1 else 0 for i in range(len(df_customer))]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/aa515119-b5ef-c7e6-9fad-4e9dc474698c.png)

#####4. 部分文字列が値の末尾にある場合に添え字を返す
[rfind('_<部分文字列>_')+1 if _<データフレーム名>_['_<カラム名>_'][i].endswith('_<部分文字列>_') else 0 for i in range(len(_<データフレーム名>_'))]

```
df_store['chome_index'] = [df_store['address'][i].rfind('丁目')+1 if df_store['address'][i].endswith('丁目') else 0 for i in range(len(df_store))]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/49b4fd21-8ec0-041b-8231-0d6bcd07d4f9.png)

#### 2. 部分文字列の登場回数の取得
◇ SPSS Modeler
count_substring(_<フィールド名>_,'_<部分文字列>_')
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/fe551285-6cb7-7457-296e-6016d2ed2279.png)

◇ Python
_<データフレーム名>_['_<カラム名>_'].str.count('_<部分文字列>_')

```
df_customer['count_higashi'] = df_customer['address'].str.count('東')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/fd3f4cf4-125b-ab8b-fa65-8464384dbd83.png)

#### 3. 文字列の長さの取得
◇ SPSS Modeler
length(_<フィールド名>_')
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/6cf65d07-5fae-a226-1c74-0cf7db15f3d2.png)

◇ Python
_<データフレーム名>_['_<カラム名>_'].str.len()

```
df_customer['name_length'] = df_customer['customer_name'].str.len()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159010/d0cb20c6-e9ed-02c3-2edd-759aa5f324a6.png)

## お断り
このサイトの掲載内容は私自身の見解であり、必ずしも所属会社の立場、戦略、意見を代表するものではありません。 記事は執筆時点の情報を元に書いているため、必ずしも最新情報であるとはかぎりません。 記事の内容の正確性には責任を負いません。自己責任で実行してください。