# Python分析美國警察槍擊案EDA
## 摘要
本文使用Python對2015-2022年美國警察槍擊案數據集進行探索性數據分析(EDA),通過Pandas、Matplotlib、Seaborn等工具揭示案件的時間分布、人口統計學特征、地理分布模式等關鍵規律,并構建交互式可視化圖表。研究發現美國警察槍擊案存在顯著的種族差異和地域聚集特征,案件數量與季節因素呈現相關性。
關鍵詞:警察槍擊案、EDA、Python、數據可視化、種族差異
## 1. 數據來源與背景
### 1.1 數據集介紹
使用華盛頓郵報整理的[Police Shooting Database](https://www.washingtonpost.com/graphics/investigations/police-shootings-database/),包含2015年1月至2022年12月期間:
- 案件數量:6,717起
- 字段維度:14個關鍵字段
- 更新頻率:實時更新
### 1.2 數據字段說明
```python
import pandas as pd
df = pd.read_csv('police_shootings.csv')
print(df.info())
# 主要字段:
# date, name, age, gender, race, city, state, signs_of_mental_illness,
# threat_level, flee, body_camera, armed_with, latitude, longitude
# 缺失值統計
missing_values = df.isnull().sum()
print(missing_values[missing_values > 0])
# 年齡缺失處理
df['age'] = df['age'].fillna(df['age'].median())
# 種族缺失處理
df['race'] = df['race'].fillna('Unknown')
# 提取時間特征
df['date'] = pd.to_datetime(df['date'])
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['day_of_week'] = df['date'].dt.day_name()
# 武器類型分類
armed_categories = {
'gun': 'Firearm',
'knife': 'Edged Weapon',
'unarmed': 'Unarmed',
'vehicle': 'Vehicle'
}
df['armed_category'] = df['armed_with'].map(armed_categories).fillna('Other')
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(12,6))
yearly_counts = df.groupby('year').size()
sns.lineplot(x=yearly_counts.index, y=yearly_counts.values, marker='o')
plt.title('Annual Trend of Police Shootings (2015-2022)')
plt.xlabel('Year')
plt.ylabel('Number of Incidents')
plt.grid(True)
plt.show()
month_order = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December']
plt.figure(figsize=(14,6))
monthly_counts = df['month'].value_counts().sort_index()
sns.barplot(x=month_order, y=monthly_counts.values, palette='coolwarm')
plt.title('Monthly Distribution of Police Shootings')
plt.xticks(rotation=45)
plt.show()
race_mapping = {
'W': 'White',
'B': 'Black',
'A': 'Asian',
'N': 'Native American',
'H': 'Hispanic',
'O': 'Other',
'Unknown': 'Unknown'
}
df['race'] = df['race'].map(race_mapping)
plt.figure(figsize=(10,6))
race_counts = df['race'].value_counts(normalize=True) * 100
race_counts.plot(kind='bar', color=sns.color_palette('husl'))
plt.title('Racial Distribution of Victims (%)')
plt.ylabel('Percentage')
plt.xticks(rotation=45)
plt.show()
plt.figure(figsize=(12,6))
sns.histplot(df['age'], bins=30, kde=True, color='royalblue')
plt.title('Age Distribution of Victims')
plt.xlabel('Age')
plt.ylabel('Count')
plt.axvline(df['age'].median(), color='red', linestyle='--',
label=f'Median: {df["age"].median():.1f}')
plt.legend()
plt.show()
state_counts = df['state'].value_counts().head(15)
plt.figure(figsize=(12,6))
sns.barplot(x=state_counts.values, y=state_counts.index, palette='viridis')
plt.title('Top 15 States by Police Shooting Incidents')
plt.xlabel('Number of Incidents')
plt.show()
import plotly.express as px
fig = px.density_mapbox(df, lat='latitude', lon='longitude',
radius=5, zoom=4,
mapbox_style="stamen-terrain")
fig.update_layout(title='Geographic Distribution of Police Shootings')
fig.show()
cross_tab = pd.crosstab(df['race'], df['armed_category'], normalize='index')*100
plt.figure(figsize=(12,8))
sns.heatmap(cross_tab, annot=True, fmt='.1f', cmap='YlOrRd')
plt.title('Armed Status by Race (%)')
plt.ylabel('Race')
plt.xlabel('Armed Category')
plt.show()
mental_illness = df['signs_of_mental_illness'].value_counts(normalize=True)*100
plt.figure(figsize=(8,6))
plt.pie(mental_illness, labels=mental_illness.index,
autopct='%1.1f%%', colors=['#ff9999','#66b3ff'])
plt.title('Percentage with Signs of Mental Illness')
plt.show()
plt.figure(figsize=(12,6))
sns.countplot(data=df, x='flee', hue='threat_level', palette='Set2')
plt.title('Threat Level by Flee Status')
plt.xlabel('Flee Status')
plt.ylabel('Count')
plt.legend(title='Threat Level')
plt.show()
import plotly.graph_objects as go
monthly_race = df.groupby(['year_month', 'race']).size().unstack()
fig = go.Figure()
for race in monthly_race.columns:
fig.add_trace(go.Scatter(
x=monthly_race.index,
y=monthly_race[race],
name=race,
mode='lines+markers'
))
fig.update_layout(title='Monthly Trends by Race',
xaxis_title='Date',
yaxis_title='Number of Incidents')
fig.show()
fig = px.scatter_3d(df.sample(1000),
x='longitude', y='latitude', z='age',
color='race', symbol='armed_category',
title='3D Distribution of Cases')
fig.update_traces(marker_size=3)
fig.show()
附錄:完整代碼獲取 GitHub倉庫鏈接 “`
注:實際寫作時需要: 1. 補充完整的數據分析過程 2. 調整可視化參數優化圖表展示 3. 添加更詳細的分析討論 4. 插入真實的圖表輸出 5. 根據最新數據更新統計數字 6. 擴展文獻綜述和方法論部分
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。