如何按邮政编码聚类:将100英里范围内的地点分组
问题
我有一个约700条记录的数据集,每条记录对应唯一ID和邮政编码(Zip Code),数据结构如下:
ID ZipCode Sales 1 15110 10,000 2 15115 15,000 3 98000 2,000 4 98001 10,000 5 70570 10,000
同时我有NBER提供的邮政编码距离数据集(仅包含100英里范围内的邮编对),结构如下:
zip1 miles_to_zip2 zip2 1534 50 1001 1534 44 1002 1534 48 1003
这个距离数据集有1300万行,但我只需要用到我那700个邮编的相关数据。我想用Python、R或Power BI实现最简方案,给每条记录加上cluster列,将100英里范围内的地点归为同一聚类(例如ID1和ID2归为cluster1,ID3和ID4归为cluster2,ID5归为cluster3)。
最简解决方案:Python实现
这是最直接的方案,利用pandas筛选数据,networkx处理图的连通分量(聚类本质是找相互连通的邮编组):
1. 筛选目标邮编的距离数据
分块读取大距离数据集,只保留和我们700个邮编相关的行,避免内存过载:
import pandas as pd # 读取自有数据集 my_data = pd.read_csv("your_data_file.csv") target_zips = my_data["ZipCode"].unique().tolist() # 分块读取并筛选距离数据 filtered_distance = pd.DataFrame() for chunk in pd.read_csv("nber_distance_file.csv", chunksize=100000): # 保留zip1或zip2属于目标邮编的行 mask = chunk["zip1"].isin(target_zips) | chunk["zip2"].isin(target_zips) filtered_distance = pd.concat([filtered_distance, chunk[mask]]) # 去重,避免重复的双向邮编对(如(zipA, zipB)和(zipB, zipA)) filtered_distance = filtered_distance.drop_duplicates(subset=["zip1", "zip2"])
2. 识别聚类(连通分量)
把邮编转化为图节点,100英里内的邮编对作为边,连通的节点即为同一聚类:
import networkx as nx # 创建无向图 G = nx.Graph() G.add_nodes_from(target_zips) # 添加边 for _, row in filtered_distance.iterrows(): G.add_edge(row["zip1"], row["zip2"]) # 生成邮编到聚类的映射 cluster_mapping = {} current_cluster = 1 for component in nx.connected_components(G): for zip_code in component: cluster_mapping[zip_code] = f"cluster{current_cluster}" current_cluster += 1 # 合并聚类信息到原数据集 my_data["cluster"] = my_data["ZipCode"].map(cluster_mapping)
3. 输出结果
my_data.to_csv("clustered_result.csv", index=False)
R实现方案
用dplyr筛选数据,igraph处理连通分量:
1. 筛选距离数据
library(dplyr) my_data <- read.csv("your_data_file.csv") target_zips <- unique(my_data$ZipCode) # 读取并筛选距离数据 filtered_distance <- read.csv("nber_distance_file.csv") %>% filter(zip1 %in% target_zips | zip2 %in% target_zips) %>% distinct(zip1, zip2, .keep_all = TRUE)
2. 生成聚类
library(igraph) # 构建图对象 g <- graph_from_data_frame(filtered_distance[, c("zip1", "zip2")], directed = FALSE) # 获取连通分量 cluster_info <- components(g) # 构建映射表 cluster_mapping <- data.frame( ZipCode = names(cluster_info$membership), cluster = paste0("cluster", cluster_info$membership) ) # 合并到原数据 clustered_data <- left_join(my_data, cluster_mapping, by = "ZipCode")
Power BI实现方案
如果习惯可视化工具,推荐直接在Power BI中嵌入Python脚本(复用上面的Python代码),步骤如下:
- 导入自有数据集和NBER距离数据集到Power BI;
- 进入转换数据界面,新建空白查询,点击运行Python脚本,粘贴前面的Python代码(注意修改文件路径为Power BI中的表名,如
my_data = dataset对应导入的自有数据表); - 运行后即可得到带
cluster列的数据集,加载到报表中使用。
内容的提问来源于stack exchange,提问作者Jurassic_Question
相关产品推荐
相关产品推荐

