You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何计算分类变量的匹配距离?求无需独热编码的替代算法

问题:无需独热编码的混合类型数据距离计算替代方案

我曾尝试用Gower距离计算数据集的距离矩阵,代码能正常运行,但发现这个方法不符合需求——Gower距离对连续变量用曼哈顿距离,二元变量用Dice距离计算相似度,所以必须把所有多分类(类别数>2)的变量做独热编码转成哑变量。但我不想用独热编码,想找替代算法,有没有合适的选择?

数据集

{'Sex': {0: 'Female',
  1: 'Female',
  2: 'Female',
  3: 'Female',
  4: 'Male',
  5: 'Male',
  6: 'Female',
  7: 'Female',
  8: 'Female',
  9: 'Male',
  10: 'Male',
  11: 'Female',
  12: 'Female',
  13: 'Female',
  14: 'Female'},
 'City': {0: 'Lagos',
  1: 'Lagos',
  2: 'Tokyo',
  3: 'London',
  4: 'Tokyo',
  5: 'Lagos',
  6: 'Cairo',
  7: 'Lagos',
  8: 'Lagos',
  9: 'Tokyo',
  10: 'Houston',
  11: 'New York',
  12: 'Lagos',
  13: 'Paris',
  14: 'Chicago'},
 'Region': {0: 'Africa',
  1: 'Africa',
  2: 'Asia Pacific',
  3: 'Europe',
  4: 'Asia Pacific',
  5: 'Africa',
  6: 'Africa',
  7: 'Africa',
  8: 'Africa',
  9: 'Asia Pacific',
  10: 'Americas',
  11: 'Americas',
  12: 'Africa',
  13: 'Europe',
  14: 'Americas'},
 'Graduated': {0: 'No',
  1: 'Yes',
  2: 'Yes',
  3: 'No',
  4: 'Yes',
  5: 'Yes',
  6: 'Yes',
  7: 'No',
  8: 'Yes',
  9: 'Yes',
  10: 'No',
  11: 'Yes',
  12: 'No',
  13: 'Yes',
  14: 'No'}}

当前实现代码

import pandas as pd
import numpy as np
import gower

df=pd.read_csv("k_mode_data.csv")

distance_matrix = gower.gower_matrix(df)

cat_df = pd.DataFrame(distance_matrix)

推荐替代方案

1. K-Prototypes 距离(适配混合类型数据)

K-Prototypes专为混合数值/分类数据设计,无需独热编码:对分类变量采用简单匹配逻辑(取值相同则距离为0,不同则为1),数值变量用欧氏距离。可以直接利用kmodes库的距离计算功能:

from kmodes.kprototypes import KPrototypes
from kmodes.util import dissim
import pandas as pd
import numpy as np

df = pd.read_csv("k_mode_data.csv")
# 将分类列转为category类型
for col in df.columns:
    df[col] = df[col].astype('category')

# 获取所有分类列的索引
cat_cols_idx = [df.columns.get_loc(col) for col in df.columns]

# 生成全量距离矩阵
distance_matrix = np.zeros((len(df), len(df)))
for i in range(len(df)):
    for j in range(len(df)):
        distance_matrix[i,j] = dissim(df.iloc[i].values, df.iloc[j].values, cat_cols_idx, cat_metric='hamming')

cat_df = pd.DataFrame(distance_matrix)

2. Hamming 距离(纯分类数据场景)

如果你的数据集全是分类变量(如示例数据),Hamming距离是最直接的选择:统计两个样本中取值不同的变量占比,无需任何编码。用scikit-learn即可快速实现:

import pandas as pd
from sklearn.metrics.pairwise import pairwise_distances

df = pd.read_csv("k_mode_data.csv")
# 将分类列转为标签编码(非独热,仅映射为整数)
df_encoded = df.apply(lambda x: x.astype('category').cat.codes)

# 计算Hamming距离矩阵
distance_matrix = pairwise_distances(df_encoded, metric='hamming')
cat_df = pd.DataFrame(distance_matrix)

3. 自定义距离函数(完全灵活控制)

如果需要自定义分类变量的距离逻辑(比如给不同变量分配权重),可以自己实现距离函数:

import pandas as pd
import numpy as np

df = pd.read_csv("k_mode_data.csv")

def custom_cat_distance(s1, s2, weights=None):
    # s1、s2为单个样本的Series
    if weights is None:
        weights = {col:1 for col in s1.index}
    # 计算每个分类变量的差异:不同则为1,相同则为0,乘以权重
    diffs = [(s1[col] != s2[col]) * weights[col] for col in s1.index]
    return sum(diffs) / sum(weights.values())

# 生成距离矩阵
distance_matrix = np.zeros((len(df), len(df)))
for i in range(len(df)):
    for j in range(len(df)):
        # 可自定义权重,比如给City列更高权重:weights={'Sex':1, 'City':2, 'Region':1, 'Graduated':1}
        distance_matrix[i,j] = custom_cat_distance(df.iloc[i], df.iloc[j])

cat_df = pd.DataFrame(distance_matrix)

内容的提问来源于stack exchange,提问作者yocodefreak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 00:05:21