Python数据分析实战:基于5年地铁犯罪数据构建多维安全评估模型【数据集可下载】
本文通过Python对纽约地铁5年犯罪数据进行深度分析,构建包含时空分布、犯罪类型权重、疫情影响等多个维度的安全评估模型,并提供完整可运行代码。
【数据集下载链接】 : 文章最后面获取
引言:从数据视角重新审视公共交通安全
当我们谈论地铁安全时,往往依赖于新闻报道和个人感受。但作为技术人员,我们应该如何用数据驱动的方式,构建一个科学、可量化的地铁安全评估体系?
本文将通过一个完整的Python项目,展示如何处理115个地铁分局、8大犯罪类型、5年时间跨度的真实数据,最终构建一个多维度的安全评估模型。
一、数据加载与结构化处理
目标:加载原始数据,理解数据结构,为后续分析打好基础。
python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime
import warnings
warnings.filterwarnings('ignore')# 设置中文显示和图表样式
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
sns.set_style("whitegrid")# 加载数据
df = pd.read_csv('nyc_subway_arrests_2020_2025.csv', encoding='utf-8')# 数据结构探索
print("数据集形状:", df.shape)
print("\n数据类型分布:")
print(df.dtypes.value_counts())
print("\n缺失值统计:")
print(df.isnull().sum())# 查看前5行数据
df.head()
二、数据预处理与特征工程
目标:清洗数据,创建衍生特征,为建模做准备。
python
# 日期格式转换
df['date'] = pd.to_datetime(df['统计月份'])
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['quarter'] = df['date'].dt.quarter# 犯罪类型标准化处理
crime_columns = ['ASSAULT_3', 'FELONY_ASSAULT', 'SEX_CRIMES', 'ROBBERY', 'DISORDERLY_CONDUCT', 'PERSONAL_INJURY']# 填充缺失值(使用0填充,表示无犯罪记录)
for col in crime_columns:df[col] = df[col].fillna(0)# 计算总犯罪数
df['total_crimes'] = df[crime_columns].sum(axis=1)# 创建犯罪严重度加权得分
# 基于犯罪类型的社会危害程度设置权重
crime_weights = {'SEX_CRIMES': 1.0, # 性犯罪权重最高'FELONY_ASSAULT': 0.8, # 重罪攻击'ROBBERY': 0.6, # 抢劫'ASSAULT_3': 0.4, # 三级攻击'PERSONAL_INJURY': 0.3, # 人身伤害'DISORDERLY_CONDUCT': 0.1 # 扰乱秩序
}# 计算加权犯罪得分
df['weighted_crime_score'] = sum(df[crime] * weight for crime, weight in crime_weights.items())print("数据预处理完成!")
print(f"时间范围: {df['date'].min()} 至 {df['date'].max()}")
print(f"涉及分局数量: {df['分局代码'].nunique()}")
三、时间序列分析:疫情对犯罪的影响
目标:分析COVID-19疫情前后犯罪模式的变化,验证公共卫生事件对城市安全的影响。
python
# 定义疫情时期划分
def get_period(date):if date < pd.Timestamp('2020-03-01'):return '疫情前'elif date < pd.Timestamp('2021-07-01'):return '疫情期间'else:return '疫情后'df['period'] = df['date'].apply(get_period)# 按月统计各类犯罪趋势
monthly_crimes = df.groupby('date')[crime_columns].sum()# 创建多子图展示各类犯罪的时间趋势
fig, axes = plt.subplots(3, 2, figsize=(15, 12))
axes = axes.flatten()for idx, crime in enumerate(crime_columns):ax = axes[idx]monthly_crimes[crime].plot(ax=ax, linewidth=2)# 标记疫情开始和结束时间点ax.axvline(x=pd.Timestamp('2020-03-01'), color='red', linestyle='--', alpha=0.7, label='疫情开始')ax.axvline(x=pd.Timestamp('2021-07-01'), color='green', linestyle='--', alpha=0.7, label='疫情缓解')ax.set_title(f'{crime} 月度趋势', fontsize=12)ax.set_xlabel('时间')ax.set_ylabel('案件数量')ax.legend()ax.grid(True, alpha=0.3)plt.tight_layout()
plt.show()# 疫情影响的统计分析
period_analysis = df.groupby('period')['total_crimes'].agg(['mean', 'std', 'sum'])
print("\n各时期犯罪统计对比:")
print(period_analysis)
四、空间分布分析:识别高危地铁线路
目标:通过空间维度分析,识别犯罪高发的地铁分局和线路。
python
# 计算各分局的犯罪风险评分
precinct_risk = df.groupby('分局代码').agg({'total_crimes': 'sum','weighted_crime_score': 'sum','SEX_CRIMES': 'sum','FELONY_ASSAULT': 'sum','ROBBERY': 'sum'
}).round(2)# 标准化风险评分(0-100分)
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler(feature_range=(0, 100))
precinct_risk['risk_score'] = scaler.fit_transform(precinct_risk[['weighted_crime_score']]
)# 风险等级划分
def get_risk_level(score):if score >= 70:return '高危'elif score >= 40:return '中危'else:return '低危'precinct_risk['risk_level'] = precinct_risk['risk_score'].apply(get_risk_level)# 可视化TOP20高危分局
top20_dangerous = precinct_risk.nlargest(20, 'risk_score')plt.figure(figsize=(12, 8))
colors = ['red' if level == '高危' else 'orange' if level == '中危' else 'green' for level in top20_dangerous['risk_level']]plt.barh(range(len(top20_dangerous)), top20_dangerous['risk_score'], color=colors)
plt.yticks(range(len(top20_dangerous)), top20_dangerous.index)
plt.xlabel('风险评分(0-100)')
plt.title('地铁分局犯罪风险评分TOP20', fontsize=14, fontweight='bold')
plt.grid(axis='x', alpha=0.3)# 添加风险等级图例
from matplotlib.patches import Patch
legend_elements = [Patch(facecolor='red', label='高危(≥70)'),Patch(facecolor='orange', label='中危(40-69)'),Patch(facecolor='green', label='低危(<40)')
]
plt.legend(handles=legend_elements, loc='lower right')
plt.tight_layout()
plt.show()
五、构建多维度安全评估模型
目标:整合时间、空间、犯罪类型等多个维度,构建综合安全评估模型。
python
class SubwaySafetyModel:def __init__(self, data):self.data = dataself.crime_weights = crime_weightsdef calculate_temporal_risk(self, precinct, month, year):"""计算特定时间的风险值"""subset = self.data[(self.data['分局代码'] == precinct) & (self.data['month'] == month) & (self.data['year'] == year)]if subset.empty:return 0return subset['weighted_crime_score'].values[0]def calculate_trend_factor(self, precinct):"""计算犯罪趋势因子(上升/下降)"""precinct_data = self.data[self.data['分局代码'] == precinct]if len(precinct_data) < 2:return 1.0# 使用线性回归计算趋势from scipy import statsx = np.arange(len(precinct_data))y = precinct_data['total_crimes'].valuesslope, _, _, _, _ = stats.linregress(x, y)# 将斜率转换为趋势因子trend_factor = 1 + (slope / np.mean(y) if np.mean(y) > 0 else 0)return np.clip(trend_factor, 0.5, 1.5) # 限制在0.5-1.5之间def get_safety_recommendation(self, precinct, datetime_str):"""基于模型给出安全建议"""dt = pd.to_datetime(datetime_str)risk_score = self.calculate_temporal_risk(precinct, dt.month, dt.year)trend = self.calculate_trend_factor(precinct)# 综合风险评分final_risk = risk_score * trendif final_risk < 30:return {'level': '安全','score': final_risk,'advice': '该线路当前相对安全,正常出行即可'}elif final_risk < 60:return {'level': '注意','score': final_risk,'advice': '建议避开深夜时段,保持警惕'}else:return {'level': '高危','score': final_risk,'advice': '建议选择替代路线或增强安全防护'}# 模型应用示例
model = SubwaySafetyModel(df)# 测试几个分局的安全评估
test_precincts = df['分局代码'].unique()[:5]
test_date = '2024-12-01'print(f"\n{test_date} 各分局安全评估结果:")
print("-" * 60)for precinct in test_precincts:result = model.get_safety_recommendation(precinct, test_date)print(f"分局 {precinct}:")print(f" 风险等级: {result['level']}")print(f" 风险分数: {result['score']:.2f}")print(f" 出行建议: {result['advice']}")print()
六、高级分析:女性出行安全专题
目标:针对特定人群(女性)的安全需求,构建专门的风险评估体系。
python
# 女性相关犯罪风险分析
female_safety_weights = {'SEX_CRIMES': 1.0, # 性犯罪权重最高'ASSAULT_3': 0.3, # 攻击类犯罪'ROBBERY': 0.2 # 抢劫(可能涉及人身安全)
}# 计算女性安全指数
df['female_safety_score'] = sum(df[crime] * weight for crime, weight in female_safety_weights.items() if crime in df.columns
)# 分析不同时段的女性安全风险
hourly_risk_patterns = {'早高峰(7-9)': 0.7, # 人多相对安全'日间(9-17)': 0.8, '晚高峰(17-19)': 0.7,'夜间(19-23)': 1.2, # 风险增加'深夜(23-7)': 1.5 # 高风险时段
}# 创建女性出行安全热力图
female_safety_by_precinct = df.groupby('分局代码')['female_safety_score'].mean()
female_safety_by_month = df.groupby('month')['female_safety_score'].mean()fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))# 按分局的安全分布
top15_unsafe = female_safety_by_precinct.nlargest(15)
ax1.bar(range(len(top15_unsafe)), top15_unsafe.values, color=plt.cm.Reds(top15_unsafe.values / top15_unsafe.max()))
ax1.set_xticks(range(len(top15_unsafe)))
ax1.set_xticklabels(top15_unsafe.index, rotation=45)
ax1.set_title('女性出行高风险分局TOP15', fontsize=12, fontweight='bold')
ax1.set_ylabel('风险指数')# 按月份的风险变化
months = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
ax2.plot(female_safety_by_month.index, female_safety_by_month.values, marker='o', linewidth=2, markersize=8)
ax2.set_xticks(range(1, 13))
ax2.set_xticklabels(months)
ax2.set_title('女性出行风险月度变化规律', fontsize=12, fontweight='bold')
ax2.set_ylabel('平均风险指数')
ax2.grid(True, alpha=0.3)plt.tight_layout()
plt.show()
本文通过Python对5年地铁犯罪数据进行了全方位分析,构建了一个包含时间序列、空间分布、人群细分等多个维度的安全评估模型。核心技术要点包括:
-
数据预处理:处理缺失值、特征工程、权重设计
-
时间序列分析:识别疫情等外部事件对犯罪的影响
-
空间分析:基于地理位置的风险热点识别
-
模型构建:整合多维度信息的综合评估体系
-
场景应用:针对特定人群的定制化分析
更多数据尽在“海数据haidats”
如果这篇文章对你有帮助,欢迎点赞👍收藏⭐关注🔔