)}"
pd.factorize()は Pandas ライブラリ内でカテゴリ変数をエンコーディングするための関数です。カテゴリデータを整数エンコーディングに変換し、同時にユニーク値のリストを返します。
これは機械学習の前処理でよく使われる手法で、テキストカテゴリを数値に変換してアルゴリズムが処理しやすくします。ワンホットエンコーディング(pd.get_dummies())とは異なり、因子化エンコーディングはデータの次元を増やしません。
単語の意味: factorize「因子化」を意味し、ここではカテゴリ変数を数値因子(整数エンコーディング)に変換することを指します。
基本構文とパラメータ
pd.factorize()は Pandas ライブラリのトップレベル関数で、カテゴリ変数を整数にエンコーディングするために使用します。
構文形式
pd.factorize(values, sort=False, na_sentinel=-1, size_hint=None)
パラメータの説明
- パラメータ:
values- 型: 配列ライクなオブジェクト。Series、リスト、配列など。
- 説明: エンコーディングするカテゴリデータ。
- パラメータ:
sort- 型: ブール値。
- が
Trueの場合、ユニーク値をソートしてからエンコーディングします。デフォルトはFalse(出現順にエンコーディング)です。
na_sentinel
- 型: 整数。
- 欠損値をマークするための整数。デフォルトは
-1です。もしNoneに設定すると、欠損値は NaN のままになります。
関数の説明
- 戻り値: タプル (codes, uniques) を返します。codes はエンコーディング後の整数配列、uniques はユニーク値の配列です。
- 効果: カテゴリ変数を 0 から始まる整数シーケンスにマッピングし、各ユニーク値が 1 つの整数に対応します。
例
簡単なものから複雑なものまでの一連の例を通して、pd.factorize()の使い方を徹底的に理解しましょう。
例1:基本用法 - カテゴリ変数のエンコーディング
例
import pandas as pd
import numpy as np
# 1. カテゴリデータを作成
colors = pd.Series(['red', 'blue', 'green', 'red', 'blue', 'yellow'])
print("=== 元のカテゴリデータ ===")
print(colors)
# 2. pd.factorize() を使用してエンコーディング
codes, uniques = pd.factorize(colors)
print("\n=== pd.factorize() エンコーディング結果 ===")
print(f"エンコーディング: {codes}") # エンコーディング後の整数
print(f"ユニーク値: {uniques}") # ユニーク値のリスト
print(f"型: {type(codes)}")
import numpy as np
# 1. カテゴリデータを作成
colors = pd.Series(['red', 'blue', 'green', 'red', 'blue', 'yellow'])
print("=== 元のカテゴリデータ ===")
print(colors)
# 2. pd.factorize() を使用してエンコーディング
codes, uniques = pd.factorize(colors)
print("\n=== pd.factorize() エンコーディング結果 ===")
print(f"エンコーディング: {codes}") # エンコーディング後の整数
print(f"ユニーク値: {uniques}") # ユニーク値のリスト
print(f"型: {type(codes)}")
実行結果の想定:
=== 原始分类数据 === 0 red 1 blue 2 green 3 red 4 blue 5 yellow 原始数据中 'red' 出现 2 次,'blue' 出现 2 次,'green' 和 'yellow' 各出现 1 次。 按出现顺序分配编码: - 'red' -> 0 - 'blue' -> 1 - 'green' -> 2 - 'yellow' -> 3 === 编码: [0 1 2 0 1 3] === 唯一值数组: ['red' 'blue' 'green' 'yellow']
コード解説:
- 返された codes は整数配列であり、各元の値が対応する整数コードに置き換えられています。
- uniques 配列にはすべてのユニーク値が格納され、エンコーディングの対応順に並んでいます。
- デフォルトでは出現順にエンコーディングが割り当てられます(最初に出現した値が 0 にエンコーディングされます)。
例2:sortパラメータ - ユニーク値をソートしてからエンコーディング
を使用するとsort=Trueユニーク値をソートしてからエンコーディングできるため、結果の予測可能性が高まります。
例
import pandas as pd
import numpy as np
# カテゴリデータを作成
colors = pd.Series(['red', 'blue', 'green', 'red', 'blue', 'yellow'])
print("=== 元のデータ ===")
print(colors)
# 1. ソートしない(デフォルト)- 出現順にエンコーディング
codes_unsorted, uniques_unsorted = pd.factorize(colors, sort=False)
print("\n=== sort=False (デフォルト) ===")
print(f"エンコーディング: {codes_unsorted}")
print(f"ユニーク値: {uniques_unsorted}")
# 2. ソート後のエンコーディング - アルファベット順
codes_sorted, uniques_sorted = pd.factorize(colors, sort=True)
print("\n=== sort=True (アルファベット順) ===")
print(f"エンコーディング: {codes_sorted}")
print(f"ユニーク値: {uniques_sorted}")
# 3. 数値のソート
numbers = pd.Series([5, 2, 8, 5, 3, 2, 9])
codes_num, uniques_num = pd.factorize(numbers, sort=True)
print("\n=== 数値ソートでのエンコーディング ===")
print(f"エンコーディング: {codes_num}")
print(f"ユニーク値: {uniques_num}")
import numpy as np
# カテゴリデータを作成
colors = pd.Series(['red', 'blue', 'green', 'red', 'blue', 'yellow'])
print("=== 元のデータ ===")
print(colors)
# 1. ソートしない(デフォルト)- 出現順にエンコーディング
codes_unsorted, uniques_unsorted = pd.factorize(colors, sort=False)
print("\n=== sort=False (デフォルト) ===")
print(f"エンコーディング: {codes_unsorted}")
print(f"ユニーク値: {uniques_unsorted}")
# 2. ソート後のエンコーディング - アルファベット順
codes_sorted, uniques_sorted = pd.factorize(colors, sort=True)
print("\n=== sort=True (アルファベット順) ===")
print(f"エンコーディング: {codes_sorted}")
print(f"ユニーク値: {uniques_sorted}")
# 3. 数値のソート
numbers = pd.Series([5, 2, 8, 5, 3, 2, 9])
codes_num, uniques_num = pd.factorize(numbers, sort=True)
print("\n=== 数値ソートでのエンコーディング ===")
print(f"エンコーディング: {codes_num}")
print(f"ユニーク値: {uniques_num}")
実行結果の想定:
=== 原始数据 === 0 red 1 blue 2 green 3 red 4 blue 5 yellow === sort=False (默认) === 编码: [0 1 2 0 1 3] 唯一值: ['red' 'blue' 'green' 'yellow'] === sort=True (按字母顺序) === 编码: [2 0 1 2 0 3] 唯一值: ['blue' 'green', 'red', 'yellow'] 按字母顺序排列:blue, green, red, yellow - blue -> 0 - green -> 1 - red -> 2 - yellow -> 3 === 数值排序编码 === 编码: [2 0 3 2 1 0 4] 唯一值: [2, 3, 5, 8, 9] 按数值排序:2, 3, 5, 8, 9 - 2 -> 0 - 3 -> 1 - 5 -> 2 - 8 -> 3 - 9 -> 4
コード解説:
sort=Trueユニーク値をソートしてからエンコーディングするため、エンコーディング順序は決定的で予測可能です。- これは結果を再現可能にする必要がある場合に役立ちます。
例3:欠損値の処理
na_sentinelパラメータは欠損値の処理方法を制御するために使用します。
例
import pandas as pd
import numpy as np
# 1. 欠損値を含むデータ
data = pd.Series(['a', 'b', np.nan, 'a', None, 'c', 'b'])
print("=== 欠損値を含むデータ ===")
print(data)
# 2. デフォルトの動作(欠損値 → -1)
codes_default, uniques_default = pd.factorize(data)
print("\n=== デフォルト処理(欠損値 = -1)===)
print(f"エンコーディング: {codes_default}")
print(f"ユニーク値: {uniques_default}")
# 3. カスタム欠損値エンコーディング(na_sentinel=-999 を模擬)
codes_custom = np.where(codes_default == -1, -999, codes_default)
print("\n=== カスタム欠損値エンコーディング(-999)===)
print(f"エンコーディング: {codes_custom}")
# 4. NaN を保持(na_sentinel=None を模擬)
codes_nan = codes_default.astype('float')
codes_nan[codes_nan == -1] = np.nan
print("\n=== NaN を保持 ===)
print(f"エンコーディング: {codes_nan}")
print(f"エンコーディング型: {type(codes_nan)
import numpy as np
# 1. 欠損値を含むデータ
data = pd.Series(['a', 'b', np.nan, 'a', None, 'c', 'b'])
print("=== 欠損値を含むデータ ===")
print(data)
# 2. デフォルトの動作(欠損値 → -1)
codes_default, uniques_default = pd.factorize(data)
print("\n=== デフォルト処理(欠損値 = -1)===)
print(f"エンコーディング: {codes_default}")
print(f"ユニーク値: {uniques_default}")
# 3. カスタム欠損値エンコーディング(na_sentinel=-999 を模擬)
codes_custom = np.where(codes_default == -1, -999, codes_default)
print("\n=== カスタム欠損値エンコーディング(-999)===)
print(f"エンコーディング: {codes_custom}")
# 4. NaN を保持(na_sentinel=None を模擬)
codes_nan = codes_default.astype('float')
codes_nan[codes_nan == -1] = np.nan
print("\n=== NaN を保持 ===)
print(f"エンコーディング: {codes_nan}")
print(f"エンコーディング型: {type(codes_nan)
実行結果の想定:
=== 包含缺失值的数据 === 0 a 1 b 2 NaN 3 a 4 None 5 c 6 b dtype: object === 默认处理(缺失值 = -1)=== 编码: [ 0 1 -1 0 -1 2 1] 唯一值: Index(['a', 'b', 'c'], dtype='object') === 自定义缺失值编码(-999)=== 编码: [ 0 1 -999 0 -999 2 1] === 保持 NaN === 编码: [ 0. 1. nan 0. nan 2. 1.] 编码类型: <class 'numpy.float64'>
例4:機械学習での応用
因子化エンコーディングは機械学習の前処理で非常に実用的であり、特にカーディナリティが高いカテゴリ変数に有効です。
例
import pandas as pd
# 1. カテゴリ変数を含む DataFrame を作成
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve', 'Frank'],
'city': ['Beijing', 'Shanghai', 'Beijing', 'Guangzhou', 'Shanghai', 'Beijing'],
'department': ['Sales', 'Engineering', 'Sales', 'HR', 'Engineering', 'Sales']
})
print("=== 元の DataFrame ===")
print(df)
# 2. カテゴリ列を因子化エンコーディング
# マッピング辞書を作成
city_codes, city_uniques = pd.factorize(df['city'])
dept_codes, dept_uniques = pd.factorize(df['department'])
print("\n=== 因子化エンコーディング結果 ===")
print(f"city エンコーディング: {city_codes.tolist()}")
print(f"city ユニーク値: {city_uniques}")
print(f"department エンコーディング: {dept_codes.tolist()}")
print(f"department ユニーク値: {dept_uniques}")
# 3. エンコーディング後の DataFrame を作成
df_encoded = df.copy()
df_encoded['city_encoded'] = city_codes
df_encoded['dept_encoded'] = dept_codes
print("\n=== エンコーディング後の DataFrame ===")
print(df_encoded)
# 4. マッピング辞書を使用して新しいデータをエンコーディング
print("\n=== マッピング辞書 ===")
city_mapping = dict(zip(city_uniques, range(len(city_uniques))))
print(f"city マッピング: {city_mapping}")
# 新しいデータをエンコーディング
new_cities = pd.Series(['Beijing', 'Shanghai', 'Shenzhen'])
new_codes = new_cities.map(city_mapping)
print(f"\n新しいデータのエンコーディング: {new_codes.tolist()}")
# 1. カテゴリ変数を含む DataFrame を作成
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve', 'Frank'],
'city': ['Beijing', 'Shanghai', 'Beijing', 'Guangzhou', 'Shanghai', 'Beijing'],
'department': ['Sales', 'Engineering', 'Sales', 'HR', 'Engineering', 'Sales']
})
print("=== 元の DataFrame ===")
print(df)
# 2. カテゴリ列を因子化エンコーディング
# マッピング辞書を作成
city_codes, city_uniques = pd.factorize(df['city'])
dept_codes, dept_uniques = pd.factorize(df['department'])
print("\n=== 因子化エンコーディング結果 ===")
print(f"city エンコーディング: {city_codes.tolist()}")
print(f"city ユニーク値: {city_uniques}")
print(f"department エンコーディング: {dept_codes.tolist()}")
print(f"department ユニーク値: {dept_uniques}")
# 3. エンコーディング後の DataFrame を作成
df_encoded = df.copy()
df_encoded['city_encoded'] = city_codes
df_encoded['dept_encoded'] = dept_codes
print("\n=== エンコーディング後の DataFrame ===")
print(df_encoded)
# 4. マッピング辞書を使用して新しいデータをエンコーディング
print("\n=== マッピング辞書 ===")
city_mapping = dict(zip(city_uniques, range(len(city_uniques))))
print(f"city マッピング: {city_mapping}")
# 新しいデータをエンコーディング
new_cities = pd.Series(['Beijing', 'Shanghai', 'Shenzhen'])
new_codes = new_cities.map(city_mapping)
print(f"\n新しいデータのエンコーディング: {new_codes.tolist()}")
実行結果の想定:
=== 原始 DataFrame ===
name city department
0 Alice Beijing Sales
1 Bob Shanghai Engineering
2 Charlie Beijing Sales
3 Diana Guangzhou HR
4 eve Shanghai Engineering
5 Frank Beijing Sales
=== 因子化编码结果 ===
city 编码: [0 1 0 2 1 0]
city 唯一值: ['Beijing' 'Shanghai' 'Guangzhou']
department 编码: [0 1 0 2 1 0]
department 唯一值: ['Sales' 'Engineering' 'HR']
=== 编码后的 DataFrame ===
name city department city_encoded dept_encoded
0 Alice Beijing Sales 0 0
1 Bob Shanghai Engineering 1 1
2 Charlie Beijing Sales 0 0
3 Diana Guangzhou HR 2 2
4 Eve Shanghai Engineering 1 1
5 Frank Beijing Sales 0 0
=== 映射字典 ===
city 映射: {'Beijing': 0, 'Shanghai': 1, 'Guangzhou': 2}
コード解説:
pd.factorize()タプルを返すため、直接アンパックしてエンコーディングとユニーク値を取得できます。- マッピング辞書を作成すると、新しいデータにも同じエンコーディングを適用でき、機械学習モデルの推論に便利です。
- 因子化エンコーディングはデータの次元を増やさないため、カーディナリティが高いカテゴリ変数の処理に適しています。
その他の拡張ヒント:
pd.factorize()順序あり・順序なしのカテゴリ変数の処理に適しています。ワンホットエンコーディング(ロジスティック回帰などのアルゴリズム用)が必要な場合は、pd.get_dummies()関数を使用してください。