hatunina’s blog

メモと日記です

pd.factorizeでカテゴリ変数を数値に変換する

カテゴリ変数をユニークな数値に変換してくるやつです(ダミー変数ではない)。

pd.factorize

まず、こんなデータフレームがあったとします。

import pandas as pd
df = pd.DataFrame({'列1': ['b', 'b', 'a', 'c', 'b'], '列2': ['あ', 'い', 'い', None, 'え']})
print(df)

# 出力
#   列1    列2
# 0  b     あ
# 1  b     い
# 2  a     い
# 3  c  None
# 4  b     え


とにかく文字列を数値に変換したい。
そんな時はpd.factorizeがなんとかしてくれる。

for column in df.columns:
    labels, uniques = pd.factorize(df[column])
    df[column] = labels
    
print(df)

# 出力
#    列1  列2
# 0   0   0
# 1   0   1
# 2   1   1
# 3   2  -1
# 4   0   2


引数にはシーケンス(list、Series)を渡します。
すると、カテゴリ変数を数値に変換したndarrayが返ってくるのでそれを元のデータフレームに戻します。
この時、Noneは-1に変換されます。
labelsuniquesの出力は以下のようになっています。

for column in df.columns:
    labels, uniques = pd.factorize(df[column])
    df[column] = labels
    print(labels)
    print(uniques)
    print('===')

# 出力
# [0 0 1 2 0]
# Index(['b', 'a', 'c'], dtype='object')
# ===
# [0 1 1 2 3]
# Index(['あ', 'い', 'え'], dtype='object')
# ===

get_indexer

uniquesにユニークなラベルが入っているわけですが、これをget_indexerを使うことで別のデータフレームのカテゴリ変数を同じ数値で変換することができます。

新しいデータフレームを定義します。

import pandas as pd
df = pd.DataFrame({'列1': ['b', 'b', 'a', 'c', 'b'], '列2': ['あ', 'い', 'い', None, 'え']})
df2 = pd.DataFrame({'列1': ['a', 'a', 'a', 'c', 'b'], '列2': ['え', 'あ', 'い', 'お', None]})
print(df)
print('\n')
print(df2)

# 出力
#   列1    列2
# 0  b     あ
# 1  b     い
# 2  a     い
# 3  c  None
# 4  b     え

#   列1    列2
# 0  a     え
# 1  a     あ
# 2  a     い
# 3  c     お
# 4  b  None


get_indexerに新しいデータフレームの列を渡して、変換します。

for column in df.columns:
    labels, uniques = pd.factorize(df[column])
    df[column] = labels
    df2_labels = uniques.get_indexer(df2[column])
    df2[column] = df2_labels
    
print(df)
print('\n')
print(df2)

# 出力
#    列1  列2
# 0   0   0
# 1   0   1
# 2   1   1
# 3   2  -1
# 4   0   2

#    列1  列2
# 0   1   2
# 1   1   0
# 2   1   1
# 3   2  -1
# 4   0  -1


元のデータフレームに存在しないカテゴリ変数はNoneと同様に-1に変換されます。

トレーニングセットで行った変換をテストセットにも適用する際に便利ですね。

参考

pandas.factorize — pandas 0.23.0 documentation

pandas.Index.get_indexer — pandas 0.23.0 documentation