新旧门店相似度匹配及销售额均值计算:无循环实现与算法优化
门店相似度匹配与销售额预测优化方案
数据集与需求
现有数据集
新门店数据集:
import pandas as pd from sklearn.preprocessing import MinMaxScaler import numpy as np stores_new = pd.DataFrame({ 'id_store': [11, 12, 13], 'size': [5, 5, 6], 'location': ['aaa', 'bbb', 'aaa'] })
旧门店数据集:
stores_old = pd.DataFrame({ 'id_store': [1, 2, 3, 4, 5], 'size': [4, 5, 5, 3, 7], 'location': ['aaa', 'bbb', 'aaa', 'ccc', 'bbb'], 'sales': [5555, 11111, 6666, 5555, 2222] })
核心需求
为每个新门店匹配3家最相似的旧门店,并计算这些旧门店的销售额均值。
当前相似度计算逻辑
现有代码通过以下方式计算相似度:
- 数值变量:经
MinMaxScaler缩放后,计算绝对差之和(得分越低越相似) - 分类变量:不匹配时计0.5,匹配计0,求和得到分类相似度得分
def numerical_data(point, data): count = [(sum(abs(a-b) for a, b in zip(point, sublist))) for sublist in data.values] return count def categorical_data(point, data): count = [(sum(0.5 for a, b in zip(point, sublist) if a != b)) for sublist in data.values] return count
待解决问题
- 如何不使用循环实现当前逻辑?旧门店数据集有上千条记录、15个变量,循环方式(如
iterrows)效率低下; - 针对数值与分类混合数据,是否有更优的相似度计算算法?
解决方案
问题1:无循环的向量化实现
利用Pandas和Numpy的向量化运算(广播机制)替代循环,大幅提升效率:
步骤1:分离变量并预处理
# 分离数值和分类变量 num_cols = ['size'] cat_cols = ['location'] # 对数值变量做MinMax缩放 scaler = MinMaxScaler() stores_old_num_scaled = scaler.fit_transform(stores_old[num_cols]) stores_new_num_scaled = scaler.transform(stores_new[num_cols])
步骤2:向量化计算相似度得分
# 数值变量:广播计算每个新门店与所有旧门店的绝对差之和 num_diff = np.abs(stores_new_num_scaled[:, np.newaxis, :] - stores_old_num_scaled).sum(axis=2) # 分类变量:计算每个新门店与旧门店的不匹配项得分(不匹配计0.5) cat_diff = (stores_new[cat_cols].values[:, np.newaxis, :] != stores_old[cat_cols].values).astype(float).sum(axis=2) * 0.5 # 总相似度得分(得分越低,相似度越高) total_diff = num_diff + cat_diff
步骤3:匹配Top3相似门店并计算销售额均值
# 对每个新门店的得分排序,取前3个旧门店的索引 top3_indices = np.argsort(total_diff, axis=1)[:, :3] # 提取对应销售额并计算均值 sales_means = stores_old['sales'].values[top3_indices].mean(axis=1) # 生成结果 stores_new_sales = pd.DataFrame({ 'id_store': stores_new['id_store'], 'sales': np.round(sales_means, 2) }) print(stores_new_sales)
输出结果与期望一致:
id_store sales 0 11 5925.33 1 12 2962.67 2 13 5925.33
问题2:更优的相似度计算算法
针对混合类型数据,推荐以下更专业的方案:
1. 数值变量优化
- 欧氏距离:替代曼哈顿距离(绝对差之和),适合关注变量间平方差异的场景,公式为$\sqrt{\sum(a-b)^2}$
- 加权距离:为业务上更重要的变量赋予更高权重(如
size权重设为2,location权重设为1) - 标准化方式调整:若数值变量服从正态分布,用
StandardScaler替代MinMaxScaler,避免极值影响
2. 分类变量优化
- Gower距离:专门为混合类型数据设计的相似度算法,自动区分数值/分类变量:
- 数值变量:计算标准化后的相对距离
- 分类变量:匹配则为0,不匹配则为1
可以通过gower库快速实现(需先安装:pip install gower),示例:
import gower # 计算所有新门店与旧门店的Gower距离矩阵 gower_dist = gower.gower_matrix(stores_new[num_cols+cat_cols], stores_old[num_cols+cat_cols]) # 取Top3相似门店计算销售额均值 top3_indices_gower = np.argsort(gower_dist, axis=1)[:, :3] sales_means_gower = stores_old['sales'].values[top3_indices_gower].mean(axis=1) - 独热编码+余弦相似度:对分类变量做独热编码后,将所有变量转为数值型,计算余弦相似度(适合分类变量基数较小的场景)
内容的提问来源于stack exchange,提问作者Veracious
相关产品推荐
相关产品推荐

