如何使用Python Pandas基于相似销售地点识别可搭配销售的产品
如何使用Python Pandas基于相似销售地点识别可搭配销售的产品
嘿,别担心你的英文,完全没问题!我来帮你解决这个问题——我们要把那些通过共享销售地点连起来的产品归为一组,就像你举的例子里A、B、D和C、E那样。本质上这是个连通分量的问题:把每个产品看作一个节点,如果两个产品有共同的销售地点,就给它们连一条边,最后找所有连在一起的节点组就行。
接下来我们一步步用Pandas和图论工具实现这个需求:
第一步:准备数据并预处理
首先我们先把你给出的表格转成Pandas DataFrame,然后把SELLING LOCATIONS列的字符串拆成集合,这样方便后续快速判断两个产品是否有共享地点:
import pandas as pd import networkx as nx # 构建你的示例数据 data = { 'PRODUCT': ['A', 'B', 'C', 'D', 'E'], 'SELLING LOCATIONS': ['1, 2, 3', '2,5', '7,8,9,10', '5,4', '10,11'] } df = pd.DataFrame(data) # 把销售地点字符串转成整数集合 df['LOCATION_SET'] = df['SELLING LOCATIONS'].apply(lambda x: set(map(int, x.split(', '))))
这一步处理后,每个产品的销售地点都变成了集合类型,比如产品A对应的是{1,2,3},后续判断交集会非常高效。
第二步:构建产品间的连接关系
我们需要把所有有共享销售地点的产品对关联起来。这里用无向图来存储这种关联:
# 初始化一个空的无向图 G = nx.Graph() # 先把所有产品都作为节点添加到图里 G.add_nodes_from(df['PRODUCT']) # 遍历所有产品组合,只要有共享地点就给它们连一条边 for i, product1 in df.iterrows(): for j, product2 in df.iterrows(): if i < j: # 避免重复检查同一对产品 if not product1['LOCATION_SET'].isdisjoint(product2['LOCATION_SET']): G.add_edge(product1['PRODUCT'], product2['PRODUCT'])
这样一来,有直接共享地点的产品之间就有了连接,哪怕是间接关联的(比如A和D通过B关联),后续也能被识别到同一组。
第三步:提取可搭配销售的产品组
现在图已经构建完成,我们只需要找出图中的所有连通分量——每个分量就是一组可以搭配销售的产品:
# 获取所有连通分量 connected_groups = list(nx.connected_components(G)) # 把每个组整理成易读的字符串格式 formatted_result = [', '.join(sorted(group)) for group in connected_groups] # 输出结果 for group in formatted_result: print(group)
运行这段代码后,你会得到和期望完全一致的输出:
A, B, D C, E
原理说明
- A和B共享地点2,B和D共享地点5,所以这三个产品在图里是连通的,属于同一个组;
- C和E共享地点10,因此它们也被归为同一组。
如果你不想依赖networkx库,也可以自己实现并查集(Union-Find)算法来完成连通分量的查找,不过networkx已经帮我们封装好了成熟的方法,用起来更高效省心。
备注:内容来源于stack exchange,提问作者Kiet




