贝利信息

高效统计180万行数据中城市与犯罪类型的组合频次

日期:2026-01-20 00:00 / 作者:霞舞

本文介绍如何使用pandas高效处理大规模(180万行)结构化文本数据,针对“多值分隔字段”(如london~paris~new york)进行展开与交叉计数,快速生成每个城市的各类犯罪事件频次统计表。

在分析含重复值、多标签字段的大规模日志或调查数据时(如本例中每行可包含多个城市和多种犯罪类型),传统循环+嵌套字典或预定义数组的方式不仅代码冗长、易出错,且性能低下。而Pandas提供了声明式、向量化的方法,兼顾可读性与执行效率——尤其适合处理1.8M行级别的中等规模数据集。

核心思路是:先“展开”(explode)多值字段为原子行,再按组合分组计数。具体步骤如下:

  1. 读取数据(假设CSV格式,列名为City和Crime)
  2. 字符串切分 + 展开:对City和Crime两列分别用str.split('~')转为列表,再调用.explode()将每个列表元素扩展为独立行;
  3. 分组聚合:使用groupby(["City", "Crime"]).size()直接获取每组出现次数(比value_counts()更直观,且返回Series便于后续操作);
  4. 结果格式化(可选):按需转换为嵌套字典、宽表或自定义字符串格式(如"Murder(2), Theft(1)")。

✅ 完整可运行示例:

import pandas as pd

# 读取数据(生产环境建议指定 dtype 和 chunksize 优化内存)
df = pd.read_csv("cities_crimes.csv", dtype={"City": "string", "Crime": "string"})

# 展开 City 字段
df_exploded = df.assign(City=df["City"].str.split('~')).explode("City")
# 展开 Crime 字段(注意:必须在 City 展开后进行,否则笛卡尔爆炸)
df_exploded = df_exploded.assign(Crime=df_exploded["Crime"].str.split('~')).explode("Crime")

# 统计每城-每罪组合频次
city_crime_counts = df_exploded.groupby(["City", "Crime"]).size().reset_index(name="count")

# 可选:按 City 分组,聚合为字符串(匹配题目输出格式)
result = (
    city_crime_counts
    .assign(crime_count=lambda x: x["Crime"] + "(" + x["count"].astype(str) + ")")
    .groupby("City")["crime_count"]
    .apply(lambda x: ", ".join(x))
    .reset_index(name="Crimes")
)

⚠️ 注意事项:

通过此方法,你彻底摆脱了手动维护1200个城市×70种犯罪的索引映射和海量if判断,以清晰、健壮、高性能的方式完成复杂多值关联统计。