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

如何转换字符串格式Series为数值集合正确计算杰卡德相似度

问题根因

计算结果错误来自两处逻辑缺陷:

  • 目标列存储的是单元素列表,列表内为逗号拼接的产品ID整串,直接转set只会得到包含整串的单元素集合,无法按单个产品ID计算交集
  • 取数时传入列名列表[column]会返回Series对象,直接转set会混入索引值,进一步干扰集合运算结果
修复方案

1. 预处理目标列

先统一把目标列处理为单个产品ID组成的集合,兼容不同行ID数量不一致的场景:

# 逐行转换:如果值是列表则先取内部字符串,按逗号拆分后转集合;如果直接是字符串则直接拆分
data[column] = data[column].apply(
    lambda x: set(x[0].split(',') if isinstance(x, list) else x.split(','))
)

处理后每行值为{'1','3','16','17','19'}格式的标准集合,可直接用于交并集运算。

2. 修正相似度计算函数

优化取数逻辑,避免循环内重复计算,返回结果保留原行索引方便匹配客户:

def set_sim(cust_id, data, column):
    sim_set = []
    # 提前缓存目标客户的产品集合与长度,减少循环内重复取数
    target_prod = data.loc[cust_id, column]
    target_len = len(target_prod)
    for idx in data.index:
        current_prod = data.loc[idx, column]
        inter_len = len(target_prod.intersection(current_prod))
        # 杰卡德相似度 = 交集大小 / 并集大小
        jaccard_sim = inter_len / (target_len + len(current_prod) - inter_len)
        sim_set.append(jaccard_sim)
    return pd.DataFrame(sim_set, index=data.index, columns=['jaccard_similarity'])

批量计算优化(可选)

如果需要计算全量客户两两之间的杰卡德相似度,可使用向量化运算替代for循环,数据量较大时运行效率可提升数十倍:

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics.pairwise import pairwise_distances

# 将集合转换为空格分隔的字符串,适配向量化输入
corpus = data[column].apply(lambda x: ' '.join(x))
# 生成客户-产品0-1矩阵,仅标记产品是否持有
cv = CountVectorizer(binary=True)
prod_matrix = cv.fit_transform(corpus)
# 杰卡德距离 = 1 - 杰卡德相似度,转换得到相似度矩阵
sim_matrix = 1 - pairwise_distances(prod_matrix, metric='jaccard')
# 转换为带客户索引的DataFrame,行列均为cust_id
sim_df = pd.DataFrame(sim_matrix, index=data.index, columns=data.index)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 11:36:29