【数据可视化-17】基于pyecharts的印度犯罪数据可视化分析

🧑 博主简介:曾任某智慧城市类企业算法总监,目前在美国市场的物流公司从事高级算法工程师一职,深耕人工智能领域,精通python数据挖掘、可视化、机器学习等,发表过AI相关的专利并多次在AI类比赛中获奖。CSDN人工智能领域的优质创作者,提供AI相关的技术咨询、项目开发和个性化解决方案等服务,如有需要请站内私信或者联系任意文章底部的的VX名片(ID:xf982831907)
💬 博主粉丝群介绍:① 群内初中生、高中生、本科生、研究生、博士生遍布,可互相学习,交流困惑。② 热榜top10的常客也在群里,也有数不清的万粉大佬,可以交流写作技巧,上榜经验,涨粉秘籍。③ 群内也有职场精英,大厂大佬,可交流技术、面试、找工作的经验。④ 进群免费赠送写作秘籍一份,助你由写作小白晋升为创作大佬。⑤ 进群赠送CSDN评论防封脚本,送真活跃粉丝,助你提升文章热度。有兴趣的加文末联系方式,备注自己的CSDN昵称,拉你进群,互相学习共同进步。

【数据可视化-17】基于pyecharts的印度犯罪数据可视化分析

  • 一、引言
  • 二、数据加载介绍
    • [2.1 导入必要的库](#2.1 导入必要的库)
    • [2.2 读取数据](#2.2 读取数据)
    • [2.3 数据探索](#2.3 数据探索)
  • 三、数据预处理
  • 四、可视化分析
    • [4.1 城市犯罪计数统计](#4.1 城市犯罪计数统计)
    • [4.2 不同犯罪领域的案件持续时间](#4.2 不同犯罪领域的案件持续时间)
    • [4.3 不同犯罪领域的警力部署](#4.3 不同犯罪领域的警力部署)
    • [4.4 犯罪类型的分布情况](#4.4 犯罪类型的分布情况)
    • [4.5 受害者性别分布](#4.5 受害者性别分布)
    • [4.6 各城市犯罪领域分布](#4.6 各城市犯罪领域分布)
    • [4.7 各种武器在犯罪类型里使用的频率](#4.7 各种武器在犯罪类型里使用的频率)
    • [4.8 受害者各年龄数量分布](#4.8 受害者各年龄数量分布)
    • [4.9 不同年龄区间的受害者数量](#4.9 不同年龄区间的受害者数量)
  • 总结

一、引言

  在当今社会,犯罪数据的分析对于理解犯罪模式、优化警力部署和提升公共安全具有重要意义。本文将利用 Python 的 pyecharts 库对 2020 年至 2024 年印度多个城市的犯罪数据进行可视化分析,涵盖多个关键维度。

二、数据加载介绍

2.1 导入必要的库

  首先,我们需要导入必要的Python库,包括pandas和pyecharts。

python 复制代码
import pandas as pd
from datetime import datetime
from pyecharts.charts import Bar, Line, Pie, Scatter, Map, Grid, Tab
from pyecharts import options as opts
from pyecharts.globals import ThemeType

2.2 读取数据

  假设我们的数据集保存在一个CSV文件中,名为india_crime.csv。

python 复制代码
data = pd.read_csv('india_crime_data.csv')

2.3 数据探索

  数据维度情况:

  数据的部分展示:

  查看数据简要概述信息:

  • Report Number - 报告编号
  • Date Reported - 报告日期
  • Date of Occurrence - 发生日期
  • Time of Occurrence - 发生时间
  • City - 城市
  • Crime Code - 犯罪代码
  • Crime Description - 犯罪描述
  • Victim Age - 受害者年龄
  • Victim Gender - 受害者性别
  • Weapon Used - 使用武器
  • Crime Domain - 犯罪领域
  • Police Deployed - 警力部署
  • Case Closed - 案件结案
  • Date Case Closed - 结案日期

  数据种缺失值情况:

三、数据预处理

  在进行可视化之前,我们需要对数据进行一些预处理,包括数据清洗、字段转换等。

python 复制代码
# 转换日期字段
df['Date Reported'] = pd.to_datetime(df['Date Reported'])
df['Date of Occurrence'] = pd.to_datetime(df['Date of Occurrence'])
df['Date Case Closed'] = pd.to_datetime(df['Date Case Closed'], errors='coerce')
df['Time of Occurrence'] = pd.to_datetime(df['Time of Occurrence'], dayfirst=True)

  缺失值处理,使用'2020-01-01'来填充'Date Case Closed'字段种的缺失值。

python 复制代码
df['Date Case Closed'] = df['Date Case Closed'].fillna(pd.to_datetime('2020-01-01'))

四、可视化分析

4.1 城市犯罪计数统计

  统计每个城市的犯罪数量,了解犯罪高发地区。

python 复制代码
# 城市犯罪计数统计
city_crime_count = df['City'].value_counts().reset_index()
city_crime_count.columns = ['City', 'Crime Count']
city_crime_count = city_crime_count.sort_values(by='Crime Count')

bar = (Bar(init_opts=opts.InitOpts(theme='dark',width='1000px', height='600px'))
            .add_xaxis(city_crime_count['City'].tolist())
            .add_yaxis("", city_crime_count['Crime Count'].tolist())
            .set_series_opts(label_opts=opts.LabelOpts(is_show=True),     #True,显示柱状图上的数字
                             )

            .set_global_opts(
                title_opts=opts.TitleOpts(title="城市犯罪计数统计",
                                         subtitle="""--公众号:NLP随手记, CSDN:云天徽上--""",
                                          pos_left="center"),
                xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=30)),  #
                legend_opts=opts.LegendOpts(is_show=True),
                visualmap_opts=opts.VisualMapOpts(
                    is_show=False,
                    pos_top='60%',
                    pos_left='40%',
                    range_color=["green", "yellow", "red", "pink", "orange", "purple"]
            )
            )
            .reversal_axis()
            
        )
bar.render("city_crime_count.html")
bar.render_notebook()

4.2 不同犯罪领域的案件持续时间

  计算不同犯罪领域的案件平均持续时间。

python 复制代码
# 不同犯罪领域的案件持续时间
df['Case Duration'] = (df['Date Case Closed'] - df['Date of Occurrence']).dt.days
df['Case Duration'] = df['Case Duration'].fillna(df['Case Duration'].median())

crime_domain_duration = df.groupby('Crime Domain')['Case Duration'].mean().reset_index()
crime_domain_duration.columns = ['Crime Domain', 'Average Duration']

c = (
    Bar(init_opts=opts.InitOpts(theme='dark',width='1000px', height='600px'))
    .add_xaxis(crime_domain_duration['Crime Domain'].tolist())
    .add_yaxis("", crime_domain_duration['Average Duration'].round(2).tolist())
    .set_series_opts(label_opts=opts.LabelOpts(is_show=True),     #True,显示柱状图上的数字
                             )
    .set_global_opts(
                title_opts=opts.TitleOpts(title="不同犯罪领域的案件持续时间",
                                         subtitle="""--公众号:NLP随手记, CSDN:云天徽上--""",
                                          pos_left="center"),
                xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=30)),  #
                legend_opts=opts.LegendOpts(is_show=True),
                visualmap_opts=opts.VisualMapOpts(
                    is_show=False,
                    pos_top='60%',
                    pos_left='40%',
                    range_color=["pink"]
            )
            )

    
)
c.render("crime_domain_duration.html")
c.render_notebook()

4.3 不同犯罪领域的警力部署

  分析不同犯罪领域所需的警力部署情况。

python 复制代码
categories = df['Crime Domain'].unique().tolist()

box_data = []
for category in categories:
    group = df[df['Crime Domain'] == category]['Police Deployed']
    box_data.append(group.tolist())  # 注意:这不是标准的箱线图数据格式!


c = (
    Boxplot(init_opts=opts.InitOpts(theme='dark',width='1000px', height='600px'))
    .add_xaxis(categories)
    .add_yaxis("", Boxplot.prepare_data(box_data))
    .set_series_opts(label_opts=opts.LabelOpts(is_show=True),     #True,显示柱状图上的数字
                             )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="不同犯罪领域的警力部署",
                                  subtitle="""--公众号:NLP随手记, CSDN:云天徽上--""",
                                  pos_left="center"),
        xaxis_opts=opts.AxisOpts(type_="category", name="区域", axislabel_opts=opts.LabelOpts(rotate=-15)),
        yaxis_opts=opts.AxisOpts(type_="value", name="警力部署"),
        datazoom_opts=[opts.DataZoomOpts(), opts.DataZoomOpts(type_="inside")],
        visualmap_opts=opts.VisualMapOpts(
                    is_show=False,
                    pos_top='60%',
                    pos_left='40%',
                    range_color=["yellow"]
            )
    )
)


c.render("crime_domain_police.html")
c.render_notebook()

4.4 犯罪类型的分布情况

  分析不同犯罪类型的分布情况。

python 复制代码
# 颜色分布
color_counts = df['Crime Description'].value_counts()
# 生成饼图数据
color_data = [(color, count) for color, count in color_counts.items()]

# 创建饼图
pie_chart = (
    Pie(init_opts=opts.InitOpts(theme='dark',width='1200px', height='600px'))
    .add("", color_data)
    # .set_colors(colors)  # 使用颜色映射列表
    .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
    .set_global_opts(
        title_opts=opts.TitleOpts(
            title='犯罪类型的分布情况',
            subtitle="""--公众号:NLP随手记, CSDN:云天徽上--""",
            pos_top='0%',
            pos_left="center",
            title_textstyle_opts=opts.TextStyleOpts(color='#228be6',font_size=15)
        ),
        # visualmap_opts=opts.VisualMapOpts(
        #     is_show=False,
        #     max_=600,
        #     pos_top='70%',
        #     pos_left='20%',
        #     range_color=["green", "yellow", "red", "pink", "orange"]
        # ),
        legend_opts=opts.LegendOpts(is_show=True, pos_right="0%", pos_top="5%",orient="vertical"),
    )
)
pie_chart.render("pie_set_color.html")
# 渲染图形
pie_chart.render_notebook()

4.5 受害者性别分布

  分析受害者的性别分布情况。

python 复制代码
# 受害者性别分布
gender_distribution = df['Victim Gender'].value_counts()
gender_distribution  = [(color, count) for color, count in gender_distribution.items()]

# 创建饼图
pie_chart = (
    Pie(init_opts=opts.InitOpts(theme='dark',width='1000px', height='600px'))
    .add("", gender_distribution)
    # .set_colors(colors)  # 使用颜色映射列表
    .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
    .set_global_opts(
        title_opts=opts.TitleOpts(
            title='受害者性别分布',
            subtitle="""--公众号:NLP随手记, CSDN:云天徽上--""",
            pos_top='0%',
            pos_left="center",
            title_textstyle_opts=opts.TextStyleOpts(color='#228be6',font_size=15)
        ),
        legend_opts=opts.LegendOpts(is_show=True, pos_right="10%", pos_top="40%",orient="vertical"),
    )
)
pie_chart.render("gender_distribution.html")
# 渲染图形
pie_chart.render_notebook()

4.6 各城市犯罪领域分布

  分析各城市的犯罪领域分布情况。

python 复制代码
from pyecharts.charts import HeatMap

city_domain_distribution = df.groupby(['City', 'Crime Domain']).size().unstack().fillna(0).reset_index()
city_domain_distribution = city_domain_distribution.melt(id_vars='City', var_name='Crime Domain', value_name='Count')

FA = city_domain_distribution[city_domain_distribution['Crime Domain'] == 'Fire Accident'][['City','Count']]
OC = city_domain_distribution[city_domain_distribution['Crime Domain'] == 'Other Crime'][['City','Count']]
TF = city_domain_distribution[city_domain_distribution['Crime Domain'] == 'Traffic Fatality'][['City','Count']]
VC = city_domain_distribution[city_domain_distribution['Crime Domain'] == 'Violent Crime'][['City','Count']]

data = FA.merge(OC,how='left',on='City',suffixes=('_df1', '_df2'))
data = data.merge(TF,how='left',on='City',suffixes=('', '_df3'))
data = data.merge(VC,how='left',on='City',suffixes=('', '_df4'))
data.columns = ['City','Fire Accident','Other Crime','Traffic Fatality','Violent Crime']

# 创建堆叠柱状图
bar = (
    Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))  # 使用明亮的主题
    .add_xaxis(data['City'].tolist())
    .add_yaxis('Fire Accident', data['Fire Accident'].tolist(), stack='stack1', color='blue', label_opts=opts.LabelOpts(is_show=False))
    .add_yaxis('Other Crime', data['Other Crime'].tolist(), stack='stack1', color='green', label_opts=opts.LabelOpts(is_show=False))
    .add_yaxis('Traffic Fatality', data['Traffic Fatality'].tolist(), stack='stack1', color='orange', label_opts=opts.LabelOpts(is_show=False))
    .add_yaxis('Violent Crime', data['Violent Crime'].tolist(), stack='stack1', color='red', label_opts=opts.LabelOpts(is_show=False))
    .set_global_opts(
        title_opts=opts.TitleOpts(title='各城市犯罪领域分布',
                                  subtitle="""--公众号:NLP随手记  CSDN:云天徽上--""",
                                  pos_left="center"),
        xaxis_opts=opts.AxisOpts(name='城市', axislabel_opts=opts.LabelOpts(rotate=45)),
        yaxis_opts=opts.AxisOpts(name='犯罪数'),
        datazoom_opts=opts.DataZoomOpts(),  # 添加滑动条功能
        legend_opts=opts.LegendOpts(is_show=True, pos_right="-5%", pos_top="40%",orient="vertical"),
        # toolbox_opts=opts.ToolboxOpts(is_show=True)  # 启用工具箱
    )
)

bar.render("city_domain_distribution.html")
bar.render_notebook()

4.7 各种武器在犯罪类型里使用的频率

  分析不同犯罪类型中各种武器的使用频率。

python 复制代码
# 各种武器在犯罪类型里使用的频率
weapon_crime_distribution = df.groupby(['Crime Description', 'Weapon Used']).size().unstack().fillna(0).reset_index()
weapon_crime_distribution = weapon_crime_distribution.melt(id_vars='Crime Description', var_name='Weapon Used', value_name='Count')

Blunt  = weapon_crime_distribution[weapon_crime_distribution['Weapon Used']=='Blunt Object'].set_index('Crime Description')['Count'].to_dict()
Explosives = weapon_crime_distribution[weapon_crime_distribution['Weapon Used']=='Explosives'].set_index('Crime Description')['Count'].to_dict()
Firearm  = weapon_crime_distribution[weapon_crime_distribution['Weapon Used']=='Firearm'].set_index('Crime Description')['Count'].to_dict()
Knife  = weapon_crime_distribution[weapon_crime_distribution['Weapon Used']=='Knife'].set_index('Crime Description')['Count'].to_dict()
Poison  = weapon_crime_distribution[weapon_crime_distribution['Weapon Used']=='Poison'].set_index('Crime Description')['Count'].to_dict()
None1  = weapon_crime_distribution[weapon_crime_distribution['Weapon Used']=='None'].set_index('Crime Description')['Count'].to_dict()
Other  = weapon_crime_distribution[weapon_crime_distribution['Weapon Used']=='Other'].set_index('Crime Description')['Count'].to_dict()

Blunt_list = [[key, value] for key, value in Blunt.items()]
Explosives_list = [[key, value] for key, value in Explosives.items()]
Firearm_list = [[key, value] for key, value in Firearm.items()]
Knife_list = [[key, value] for key, value in Knife.items()]
Poison_list = [[key, value] for key, value in Poison.items()]
None1_list = [[key, value] for key, value in None1.items()]
Other_list = [[key, value] for key, value in Other.items()]

c = (
    Pie(init_opts=opts.InitOpts(theme='dark',width='1400px', height='700px'))
    .add(
        "",
        Blunt_list,   # 两个值
        radius=["15%", "20%"],  # 大小
        center=["10%", "20%"],  # 位置
        rosetype="radius",   
        label_opts=opts.LabelOpts(is_show=False),  # 不在图形上显示数据
    )
    .add(
        "",
        Explosives_list,   # 两个值
        radius=["15%", "20%"],  # 大小
        center=["40%", "20%"],  # 位置
        rosetype="radius",   
        label_opts=opts.LabelOpts(is_show=False),  # 不在图形上显示数据
    )
    .add(
        "",
        Firearm_list,   # 两个值
        radius=["15%", "20%"],  # 大小
        center=["70%", "20%"],  # 位置
        rosetype="radius",   
        label_opts=opts.LabelOpts(is_show=False),  # 不在图形上显示数据
    )
    .add(
        "",
        Knife_list,   # 两个值
        radius=["15%", "20%"],  # 大小
        center=["10%", "50%"],  # 位置
        rosetype="radius",   
        label_opts=opts.LabelOpts(is_show=False),  # 不在图形上显示数据
    )
    .add(
        "",
        Poison_list,   # 两个值
        radius=["15%", "20%"],  # 大小
        center=["40%", "50%"],  # 位置
        rosetype="radius",   
        label_opts=opts.LabelOpts(is_show=False),  # 不在图形上显示数据
    )
    .add(
        "",
        None1_list,   # 两个值
        radius=["15%", "20%"],  # 大小
        center=["70%", "50%"],  # 位置
        rosetype="radius",   
        label_opts=opts.LabelOpts(is_show=False),  # 不在图形上显示数据
    )
    .add(
        "",
        Other_list,   # 两个值
        radius=["15%", "20%"],  # 大小
        center=["40%", "80%"],  # 位置
        rosetype="radius",   
        label_opts=opts.LabelOpts(is_show=False),  # 不在图形上显示数据
    )
    .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
    .set_global_opts(
        title_opts=opts.TitleOpts(
            title='各种武器在犯罪类型里使用的频率',
            subtitle="""--公众号:NLP随手记, CSDN:云天徽上--""",
            pos_top='0%',
            pos_left="center",
            title_textstyle_opts=opts.TextStyleOpts(color='#228be6',font_size=15)
        ),
        legend_opts=opts.LegendOpts(is_show=True, pos_right="0%", pos_top="20%",orient="vertical"),
    )
)

c.render("weapon_domain_distribution.html")
c.render_notebook()

4.8 受害者各年龄数量分布

  分析受害者年龄的分布情况。

python 复制代码
age_distribution = df['Victim Age'].value_counts().reset_index()
age_distribution.columns = ['Age', 'Count']
age_distribution = age_distribution.sort_values(by='Age')

# 创建散点图
scatter = (
    Scatter(init_opts=opts.InitOpts(theme='dark',width='1000px', height='600px'))
    .add_xaxis(age_distribution['Age'].tolist())
    .add_yaxis("", age_distribution['Count'].tolist(), symbol_size=10,
        label_opts=opts.LabelOpts(is_show=False),
        itemstyle_opts=opts.ItemStyleOpts(color="skyblue", opacity=0.6))  # 设置散点大小
    .set_global_opts(
        title_opts=opts.TitleOpts(
            title='受害者性别分布',
            subtitle="""--公众号:NLP随手记, CSDN:云天徽上--""",
            pos_top='0%',
            pos_left="center",
            title_textstyle_opts=opts.TextStyleOpts(color='#228be6',font_size=15)
        ),
        xaxis_opts=opts.AxisOpts(type_="category", name="受害者年龄",boundary_gap=False,max_=82),
        yaxis_opts=opts.AxisOpts(type_="value", name="数量",
                                 max_=max(age_distribution['Count'].tolist())+30, 
                                 min_=min(age_distribution['Count'].tolist())-30),
        visualmap_opts=opts.VisualMapOpts(
                    type_="size",
                    is_show=False,
                    pos_top='60%',
                    pos_left='40%',
                    range_color=["purple"],
                    max_=max(age_distribution['Count'].tolist()),
                    min_=min(age_distribution['Count'].tolist())
            ),
        # visualmap_opts=opts.VisualMapOpts(type_="size"),  # 根据数量设置散点大小
        tooltip_opts=opts.TooltipOpts(formatter="{b}: {c}"),  # 鼠标悬停提示
        
    )
)

scatter.render("age_distribution.html")
scatter.render_notebook()

4.9 不同年龄区间的受害者数量

  分析不同年龄区间的受害者数量分布情况。

python 复制代码
bins = [0, 17, 24, 34, 44, 54, 64, 74, 84, 94, 1000]
labels = ['0-17', '18-24', '25-34', '35-44', '45-54', '55-64', '65-74', '75-84', '85-94', '95+']
df['Age Group'] = pd.cut(df['Victim Age'], bins=bins, labels=labels, right=True)
# 将 Age Group 转换为有序类别
df['Age Group'] = pd.Categorical(df['Age Group'], categories=labels, ordered=True)
# 计算每个年龄区间的数量
vic_age = df['Age Group'].value_counts()

gender_distribution  = [(color, count) for color, count in vic_age.items()]

# 创建饼图
pie_chart = (
    Pie(init_opts=opts.InitOpts(theme='dark',width='1000px', height='600px'))
    .add("", gender_distribution)
    # .set_colors(colors)  # 使用颜色映射列表
    .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
    .set_global_opts(
        title_opts=opts.TitleOpts(
            title='不同年龄区间的受害者数量分布',
            subtitle="""--公众号:NLP随手记, CSDN:云天徽上--""",
            pos_top='0%',
            pos_left="center",
            title_textstyle_opts=opts.TextStyleOpts(color='#228be6',font_size=15)
        ),
        legend_opts=opts.LegendOpts(is_show=True, pos_right="10%", pos_top="40%",orient="vertical"),
    )
)
pie_chart.render("age_group_distribution.html")
# 渲染图形
pie_chart.render_notebook()

总结

  以上代码实现了对印度犯罪数据的10个关键维度的可视化分析。通过 pyecharts,我们能够直观地展示城市犯罪数量、犯罪领域、警力部署、受害者特征等多方面的信息。这些可视化图表可以帮助研究人员、政策制定者和执法机构更好地理解犯罪模式,从而制定更有效的公共安全策略。

相关推荐
ahccqw1 小时前
OpenCV 缩放 与 位移
人工智能·opencv·计算机视觉
长不大的杨瑞杰1 小时前
OpenCode v2 GitLab 集成实战:Issue 驱动开发、MR 审查与 CI/CD 最小权限
人工智能·ci/cd·gitlab·ai编程·opencode
深蓝AI2 小时前
美团 LongCat-2.5 拆解:1.6T 参数只激活 3%,1M 上下文卖 0.3 美元,Agent 模型的账变了
人工智能·llm
小和尚同志7 小时前
54.6k star 的 Multica: 集多 Agent 和看板于一体的 AI 平台
人工智能·aigc·three.js
一枕槐安4877 小时前
少样本提示(Few-shot)在业务场景的落地实践
大数据·人工智能·意图分类·mmr多样性·knn检索·动态示例选择
王中阳Go8 小时前
后端转 Agent 岗面试怎么答:8 个高频问题与应答口径
人工智能·后端·python·大语言模型
海宇AI8 小时前
零信任架构实战:基于海宇个人风险报告构建自动化分期商城信用额度初审网关
运维·人工智能·架构·自动化
tellmewhoisi8 小时前
深度学习32:卷积神经网络:卷积层(卷积运算,填充,步幅)
人工智能·深度学习·cnn
weixin_307779139 小时前
RAG 面试陷阱——混合检索并非无条件优越:一个条件反转实验
人工智能·python·面试·职场和发展
Sinokap9 小时前
OpenAI 披露 AI 安全实验:智能体如何突破隔离边界?
人工智能·安全