Guwaaago!

グワーゴ!岡山で働くIT系の人。このサイトにはWEB系の知識を記すこととす。

複数列に入っている文字列をもとにカテゴリー分けする

複数の列に文字列(カテゴリー)が入っていて、それらをもとに新たに分類する。

 ID  cat1    cat2    cat3
0   a1  S_1 Z_1 Z_1
1   a2  Z_1 S_1 NaN
2   a3  S_2 S_1 S_1
3   a4  Z_2 Z_2 Z_2
4   a5  S_3 NaN NaN
5   a6  Z_3 NaN NaN
6   a7  S_4 NaN NaN
7   a8  Z_4 NaN NaN
8   a9  S_5 NaN NaN
9   a10 Z_5 NaN NaN
10  a11 S_6 NaN NaN

こんな感じのデータがある。

cat1(カテゴリー1)と、2と3の値を元に新たなカテゴリーを作る

  • SとZ、どちらも含む場合はSHAREカテゴリー
  • Sのみの場合はSカテゴリー
  • Zのみの場合はZカテゴリー

ひとまずcat1~の1文字目だけをスライス。

df["cat1_type"] = df["cat1"].str[:1]
df["cat2_type"] = df["cat2"].str[:1]
df["cat3_type"] = df["cat3"].str[:1]

なんかもっといい書き方がある気がする...。

 ID  cat1    cat2    cat3    cat1_type   cat2_type   cat3_type
0   a1  S_1 Z_1 Z_1 S   Z   Z
1   a2  Z_1 S_1 NaN Z   S   NaN
2   a3  S_2 S_1 S_1 S   S   S
3   a4  Z_2 Z_2 Z_2 Z   Z   Z
4   a5  S_3 NaN NaN S   NaN NaN
5   a6  Z_3 NaN NaN Z   NaN NaN
6   a7  S_4 NaN NaN S   NaN NaN
7   a8  Z_4 NaN NaN Z   NaN NaN
8   a9  S_5 NaN NaN S   NaN NaN
9   a10 Z_5 NaN NaN Z   NaN NaN
10  a11 S_6 NaN NaN S   NaN NaN

列ごとに判定して、新しいカテゴリー列に結果を入れるというやり方が思いつかなかった。
1文字にしたカテゴリを連結して、正規表現で抽出する方法を採ることにする。

df = df.fillna("X") # 欠損値NaNが含まれる要素を連結すると欠損値NaNとなるため
df["cat_types"] = df['cat1_type'] + df['cat2_type'] + df['cat3_type'] 
df

合体したやつのうち、ZもSも含むものをstr.containsメソッドで抽出。

df_share = df[df['cat_types'].str.contains('^(?=.*Z)(?=.*S).*$')]
df_share

    ID  cat1    cat2    cat3    cat1_type   cat2_type   cat3_type   cat_types
0   a1  S_1 Z_1 Z_1 S   Z   Z   SZZ
1   a2  Z_1 S_1 X   Z   S   X   ZSX

おお、できた。あとはカテゴリを新たに振るなり別ファイルにするなり。