如何基于PySpark DataFrame获取并可视化违章地点与代码Top10
搞定Violation_Code的Top10可视化+优化统计逻辑
你已经完成了违章地点Top10的柱状图,接下来咱们把违章代码的Top10也做出来,顺便优化下统计逻辑——你的原始查询是按Violation_Location+Violation_Code组合分组的,得到的Ticket_Frequency是该组合的违章次数,不是单个字段的总频次,这会导致你没法直接拿到单个地点/代码的Top10,具体方案如下:
第一步:单独统计两个字段的总违章频次
直接在原表上统计单个字段的总次数,比先组合再聚合更高效:
统计违章地点的总频次(排除null值)
# 直接统计每个有效地点的总违章次数,取Top10 location_top10 = spark.sql(""" SELECT Violation_Location, COUNT(*) as Total_Tickets FROM table_view2 WHERE Violation_Location IS NOT NULL GROUP BY Violation_Location ORDER BY Total_Tickets DESC LIMIT 10 """)
统计违章代码的总频次
# 统计每个违章代码的总次数,取Top10(代码本身一般不会为null,无需额外过滤) code_top10 = spark.sql(""" SELECT Violation_Code, COUNT(*) as Total_Tickets FROM table_view2 GROUP BY Violation_Code ORDER BY Total_Tickets DESC LIMIT 10 """)
如果你坚持要用之前的组合分组结果Precint来计算,也可以这样二次聚合:
# 基于已有的Precint表,聚合得到地点总频次 location_total = spark.sql(""" SELECT Violation_Location, SUM(Ticket_Frequency) as Total_Tickets FROM Precint WHERE Violation_Location IS NOT NULL GROUP BY Violation_Location ORDER BY Total_Tickets DESC LIMIT 10 """) # 聚合得到代码总频次 code_total = spark.sql(""" SELECT Violation_Code, SUM(Ticket_Frequency) as Total_Tickets FROM Precint GROUP BY Violation_Code ORDER BY Total_Tickets DESC LIMIT 10 """)
第二步:绘制违章代码的Top10柱状图
和你绘制地点的逻辑一致,转换为Pandas后调整样式让图表更美观:
import matplotlib.pyplot as plt # 转成Pandas DataFrame code_df = code_top10.toPandas() # 绘图 plt.figure(figsize=(10, 6)) code_df.plot(x='Violation_Code', y='Total_Tickets', kind='bar', color='#ff9933') plt.title("Top 10 Violation Codes by Ticket Frequency", fontsize=14) plt.xlabel("Violation Code", fontsize=12) plt.ylabel("Total Ticket Count", fontsize=12) plt.xticks(rotation=0) # 代码标签保持水平,方便阅读 plt.tight_layout() plt.show()
第三步:(可选)同时展示两个Top10的对比图
如果想把两个图放在一起对比,用子图布局更直观:
# 获取两个Top10数据 location_df = location_top10.toPandas() code_df = code_top10.toPandas() # 创建1行2列的子图 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(18, 7)) # 绘制地点Top10 location_df.plot(x='Violation_Location', y='Total_Tickets', kind='bar', ax=ax1, color='#1a75ff') ax1.set_title("Top 10 Violation Locations", fontsize=14) ax1.set_xlabel("Precinct", fontsize=12) ax1.set_ylabel("Total Ticket Count", fontsize=12) # 绘制代码Top10 code_df.plot(x='Violation_Code', y='Total_Tickets', kind='bar', ax=ax2, color='#ff9933') ax2.set_title("Top 10 Violation Codes", fontsize=14) ax2.set_xlabel("Violation Code", fontsize=12) ax2.set_ylabel("Total Ticket Count", fontsize=12) plt.tight_layout() plt.show()
关键注意点
- 原始组合分组的问题:你之前的
Precint表是按地点+代码组合统计的,每条记录是某个地点的某个代码的违章次数,不是单个地点/代码的总次数,必须重新聚合才能得到单个字段的Top10。 - null值处理:如果不需要统计
Violation_Location为null的记录,在SQL里加WHERE Violation_Location IS NOT NULL过滤即可。 - 图表优化:调整
figsize、字体大小和坐标轴旋转角度,能让图表更易读,比如代码标签保持水平就好。
内容的提问来源于stack exchange,提问作者wjie08
相关产品推荐
相关产品推荐

