最近這段時間,發生在美國的警察槍殺嫌疑人事件頻繁出現在各個媒體,這些事件都在強調美國警察濫用權力。說實話,當初去美國西部自駕的時候,我們在路上還是有點擔心遇到警察的,因為真的不清楚這些警察會怎麼對待我們,不過還好,因為我們開車還算守法,沒有遇到任何的警察攔車。現在我用華盛頓郵報維護的一份數據,通過數據可視化的方式來看看2015年到目前為止,發生在美國的警察槍殺嫌疑人事件是怎麼樣的。
為了更好的可視化效果,這次沒有用Matplotlib和Seaborn,而是換成了Plotly,同時用Folium來把數據放到地圖上.
import pandas as pdimport plotly.express as pximport plotly.graph_objects as goimport folium這份數據的最新更新時間是2020年9月28號
all_data = pd.read_csv('./fatal-police-shootings-data.csv', parse_dates=True, squeeze=True,index_col=2)
首先還是簡單看看數據是什麼樣子的
數據裡面除了姓名,年齡,性別以及族裔信息外,還有案件的地點以及經緯度信息,還有發生時警察使用了什麼武器,嫌疑人是否逃跑以及嫌疑人攻擊警察的類型,看來信息還是挺豐富的。
再來看看數據量
(5652, 16)
這意思是說,從2015年1月1日到2020年9月28日,已經有總共5652人死於美國警察的槍下(哦對了,應該也包括膝蓋)。
接著處理一下缺失值:
# 對於Name為空的,我們直接用NoName來填充all_data['name'].fillna(value='NoName', inplace=True)# Armed欄位表示嫌疑人被警察射殺時,是否用武器以及用了什麼武器,對於為空的欄位,我們用UnKnown代替all_data['armed'].fillna(value='unknown weapon', inplace=True)all_data['gender'].fillna(value='M', inplace=True)all_data['flee'].fillna(value='UnKnown',inplace = True)接著我們看看年齡的情況
all_data['age'].describe()從上面看出,被槍殺的人平均(Mean)年齡37歲,最小(Min)的6歲(What???美國警察連6歲小孩都沒有放過?),最大(Max)91歲,年齡中值(Median)是35歲,下面再看看年齡的分布。
fig = px.histogram(all_data, x="age", color='gender',barmode='overlay', opacity=1, title='不同性別按年齡的分布情況(2015年1月-2020年9月)',width=800)fig.update_layout(xaxis_title='年 齡', yaxis_title='總數',titlefont=dict(size=18), legend=dict(title='性別',x=0.8,font=dict(size=12)), plot_bgcolor='white')從上面的直方圖可以看出來,整體年齡偏年輕。不過為了不影響真實趨勢,對缺失的年齡就不做填充了。
來看看性別比例,絕大數被射殺的都是男性。
df_gender = all_data.groupby('gender').agg('count')df_gender.sort_values('id', inplace=True, ascending=False)df_gender.reset_index(inplace=True)
fig = px.bar(df_gender,x='gender',y='id',color='gender',text='id',width=400) fig.update_traces(texttemplate='%{text:.f}', textposition='outside')fig.update_layout(uniformtext_minsize=8, uniformtext_mode='hide', title_text='案件涉及人性別對比(2015年1月-2020年9月)',xaxis_title='',yaxis_title='', plot_bgcolor='white', legend=dict(title='性別',x=0.8,font=dict(size=14)), xaxis=dict(tickfont=dict(size=14),ticklen=1) )下面我們來看看這些案件每年發生的數量:
df = all_data.groupby('year').agg('count')df.reset_index('year',inplace = True)
fig = px.bar(df, y='id', x='year', text='id',width=600)fig.update_traces(texttemplate='%{text:.f}', textposition='outside',width=0.7,textfont=dict(size=14)) fig.update_layout(uniformtext_minsize=8, uniformtext_mode='hide', title_text='每年案件發生總數(2015年1月-2020年9月)',xaxis_title='',yaxis_title='',titlefont=dict(size=22), xaxis=dict(tickfont=dict(size=14)),yaxis=dict(showticklabels=False),title=dict(xref='paper'), plot_bgcolor='white')從上圖可以看出來,每年幾乎都超過960人被警察射殺身亡,其中最多的是2019年,達到了999人。這裡還有一個有意思的趨勢,自2016年川普上臺以後,警察射殺案件是逐年上升的。
我們再來看看這些案件在美國各個州和城市發生的情況,首先是按州來統計:
df = all_data.groupby('state').agg('count')df.sort_values('id', ascending=False, inplace=True)df.reset_index(inplace=True)fig = px.bar(df[df['id'] > 100], x='state', y='id', text='id', title="<b>從每個州被槍殺總人數的角度來看(2015年1月-2020年9月):</b><br>加利福尼亞(CA)、德克薩斯(TX)和佛羅裡達(FL)是前三甲,<br>亞利桑那(AZ)緊隨其後,但加州就是要給人一騎絕塵的感覺!", width=900)# fig.update_traces(textposition="outside")fig.update_layout(plot_bgcolor="white", xaxis_title='', yaxis_title='', title=dict( font=dict(size=18), xref='paper'), yaxis=dict(showticklabels=False), )然後是按城市的統計,不過由於城市太多了,我們就看前10名吧:
df = all_data.groupby('city').agg('count')df.sort_values('id', ascending=False, inplace=True)df.reset_index(inplace=True)
fig = px.bar(df.head(10), x='city', y='id', text='id', title="前三名的洛杉磯(Los Angeles)、鳳凰城(Phoenix)和休斯頓(Houston)都是<br>耳熟能詳的城市,但是拉斯維加斯(Las Vegas)進不了前三甲還是有點讓人意外", width=900)# fig.update_traces(textposition="outside") fig.update_layout(plot_bgcolor="white", xaxis_title='', yaxis_title='', title=dict( font=dict(size=18), xref='paper'), yaxis=dict(showticklabels=False), )從這次美國國內的示威遊行和暴亂來看,警察射殺案件往往跟黑人有很大關係,那我們就來看看,警察的射殺跟族裔到底有什麼樣的關聯。
df = all_data.groupby('race').agg('count')df.sort_values('id', ascending=False, inplace=True)df.reset_index(inplace=True)
fig = px.bar(df, x='race', y='id', text='id', title="如果光從上面的數據看,白人是最多的,其次是黑人,拉丁裔第三,然後是亞裔,<br>美洲土著,其他.但是光看絕對值也不行,因為美國的白人人口佔大多數,從比例<br>上來講,也應該是白人多。", width=900)fig.update_layout(xaxis=dict(tickmode='array', tickvals=[0, 1, 2, 3, 4, 5], ticktext=['白人', '黑人', '拉丁裔', '亞裔', '土著', '其他'], tickfont=dict(size=16)), plot_bgcolor="white", xaxis_title='', yaxis_title='', title=dict( font=dict(size=18), xref='paper'), yaxis=dict(showticklabels=False),
)所以為了得到一個更客觀和公平的角度,我們還要從人口數的角度來比較。為了這點,我還專門去美國人口調查局官網(Census.gov)找來了最近的數據。
從圖上看,美國官方預測到2019年,總人口數是為3億2千8百萬人左右,其中:
白人佔比60.1%,共約2億人
黑人佔比13.4%,約4千4百萬人
拉丁裔佔16.2%, 約5千3百萬人
亞裔佔5.9%,約1千9百萬人
至於其他族裔,人數太少,我們就不統計了,看看這最多的族裔的情況。
所以為了更好的對比族裔之間的差異,我們把數據換算成每百萬人被射殺的數量。
ser = all_data.groupby('race').agg('count')['id']df =ser.to_frame() df.rename(columns={'id':'Number'},inplace=True) df.reset_index(inplace=True)df.drop(index=[3,4],inplace=True) df.sort_values(by='Number',ascending=False,inplace=True)df['pop'] =[200000000,44000000,53000000,19000000]df['npm'] = df['Number']/df['pop']*1000000df.sort_values('npm',ascending=False,inplace=True)
fig = px.bar(df, x="race", y="npm", text="npm", width=750, title="<b>各族裔每百萬人被警察槍殺的人數(2015年1月-2020年9月):</b><br>從數字上來看,在不考慮各族裔犯罪比例的前提下,<b>黑人</b>每百萬人被警察槍殺的人數最多,<br>並且比例幾乎是白人的<b>三倍</b>.")fig.update_traces(texttemplate='%{text:.2s}')fig.update_layout(title=dict(font=dict(size=16), xref='paper'), plot_bgcolor='white', xaxis=dict(tickmode='array', tickvals=[0, 1, 2, 3], ticktext=['黑人', '拉丁裔', '白人', '亞裔'], tickfont=dict(size=16), title='',ticklen=3), yaxis = dict(showticklabels=False,title=''), )前面在介紹數據的時候提到,數據裡包含了嫌疑人是否逃跑的信息,我們來看一下:
colors = ['lightslategray',] * 5colors[0] = 'crimson'
df_flee = all_data.groupby('flee').agg('count')df_flee.reset_index(inplace = True)df_flee.sort_values('id',ascending=False, inplace = True)
fig = px.bar(df_flee,x='flee',y='id',text='id',color='flee', color_discrete_sequence=colors, title='<b>警察射殺事件中嫌疑人逃跑情況(2015年1月-2020年9月):</b><br>可見在絕大多數的事件中,嫌疑人都是在並未逃跑的情況下被警察射殺的。')
fig.update_layout(title=dict(font=dict(size=16), xref='paper'), plot_bgcolor='white', xaxis=dict(tickmode='array', tickvals=[0, 1, 2, 3,4], ticktext=['未逃跑','乘車逃跑','未藉助交通工具', '未知方式','其他方式'], tickfont=dict(size=16), title='',ticklen=3), yaxis = dict(showticklabels=False,title=''),showlegend=False, )一般來講,警察執勤都是要有執法攝像機的,要麼在車上,要麼在隨身攜帶,正好數據中有這個信息,我們來看看:
df_camera = all_data.groupby('body_camera').agg('count')df_camera.reset_index(inplace = True)df_camera.sort_values('id',ascending=False, inplace = True)fig = px.bar(df_camera,x='body_camera',y='id',text='id',color='body_camera',color_discrete_sequence=['crimson','lightslategrey'],title='<b>警察射殺事件中警察隨身攝像頭佩戴情況(2015年1月-2020年9月):</b><br>可見在絕大多數的事件中,警察都沒有配備隨身攝像頭或沒有影像記錄,<br>這可能也意味著當這些射殺發生後,各方無法利用視頻證據來檢視案情,只能更多聽當事警察的描述。')fig.update_layout(title=dict(font=dict(size=16), xref='paper'), plot_bgcolor='white', xaxis=dict(tickmode='array', tickvals=[0, 1, 2, 3,4], ticktext=['無隨身攝像頭記錄','有隨身攝像頭記錄'], tickfont=dict(size=16), title='',ticklen=3), yaxis = dict(showticklabels=False,title=''),showlegend=False, )根據記錄,警察射殺案件中,有很多記錄了嫌疑人的精神狀態的問題,來看一下:
df_mental=all_data.groupby(['race','signs_of_mental_illness']).agg('count')df_mental.reset_index(inplace = True)df_mental.sort_values('id',ascending=False, inplace = True)fig = px.bar(df_mental,barmode='group',x="race", y="id", text='id',color="signs_of_mental_illness", title="<b>案件中各族裔人群精神問題狀態的對比(2015年1月-2020年9月):</b><br>可以看出白人中有精神問題的比例(29.5%)是最高的,其次是亞裔為24.7%,<br>黑人的反而才15.5%,說明發生這些事件時,黑人更大比例處於清醒狀態")fig.update_layout(title=dict(xref='paper',font=dict(size=20)), plot_bgcolor='white', xaxis=dict(tickmode='array', tickvals=[0, 1, 2, 3, 4,5], ticktext=['白人', '黑人', '拉丁裔', '亞裔', '土著', '其他'], tickfont=dict(size=16),title=''), yaxis=dict(showticklabels=False,title=''), legend=dict(y=0.5,x=0.9,title=dict(text='精神問題狀態')) )另外,我們還可以看看事件發生時,各族裔精神狀態與年齡的關係,這裡我用一個動圖:
fig = go.Figure()fig.add_trace(go.Violin( x=all_data['race'][all_data['signs_of_mental_illness'] == True], y=all_data["age"][all_data['signs_of_mental_illness'] == True], legendgroup='Yes', scalegroup='Yes', name='有症狀', side='positive', line_color='red'))fig.add_trace(go.Violin( x=all_data['race'][all_data['signs_of_mental_illness'] == False], y=all_data["age"][all_data['signs_of_mental_illness'] == False], legendgroup='Yes', scalegroup='Yes', name='無症狀', side='negative', line_color='green'))fig.update_layout(xaxis=dict(tickmode='array', tickvals=[0, 1, 2, 3, 4,5], ticktext=['白人', '黑人', '拉丁裔', '亞裔', '土著', '其他'], tickfont=dict(size=16)), title=dict(text="事件中各族裔精神病狀態與年齡關係對比(2015年1月-2020年9月)", xref="paper"), width=800,legend=dict(font=dict(size=14)), titlefont=dict(size=22))接著我們來看看這些人在被射殺的時候,是否有武器以及用的什麼武器
all_data['armed'].unique()簡單用機器來翻譯一下吧,好傢夥!真是啥都可以當武器啊,不過那個「承包商水平」是個啥東西?
"槍"," 無武裝", "玩具武器", "釘子槍", "刀", "未知", "鏟","車","錘子","斧頭","劍","砍刀", "盒子切割機","不確定","金屬物體","螺絲刀", "割草機刀片"," 旗杆", "槍和炸藥", "無繩鑽"," 十字弓", "金屬杆", "電擊槍" , "金屬管", "金屬手工工具","鈍器","金屬棒","鋒利的物體", "肉切刀"," 劫車" "鏈" " "承包商水平", "未知武器","訂書機","啤酒瓶","豆袋槍", "棒球棒和壁爐撲克", "直邊剃鬚刀", "槍和刀"," 斧頭 ", "磚頭", "棒球棒", "手火炬", "鏈鋸"," 花園工具", "剪刀", "杆" , "拾斧" , "手電筒"," 坎託" , "矛", "椅子", "草叉", "斧頭和槍", "巖石", "一塊木頭", "刺刀", "管道", "玻璃碎片"," 摩託車", "胡椒噴霧", "金屬鏟" , "撬棍"," 槳", "砍刀和槍", "輪胎鐵", "空調","杆和刀","棒球棒和瓶子", "煙花","筆","鏈鋸","槍和劍","槍和汽車", "彈丸槍", "聲稱有武器", "Bb 槍", "燃燒裝置", "武士劍","弓箭","槍和車", "車輛和槍"," 扳手", "手杖", "酒吧工具", "手榴彈","BB 槍和車輛", "黃蜂噴霧", "氣手槍", "氣軟手槍","棒球棒和刀","車輛和砍刀", "碎冰錐", "汽車, 刀和狼牙棒", "瓶子", "槍和砍刀"
武器花樣挺多,我們對排名前10位的做一個排序看看
df = all_data.groupby('armed').agg('count')df.sort_values('id', ascending=False, inplace=True)df.reset_index(inplace=True)fig = px.bar(df.head(10), x='armed', y='id', text='id', title='<b>事件發生時嫌疑人武器持有情況(2015年1月-2020年9月):</b><br>可以看出,事件發生時,嫌疑人<b>持槍</b>的數量是最多的,其次是<b>持刀</b>,<br>但是依然有高達<b>357</b>個<b>沒有任何武器</b>的人被射殺,所以說過度執法的情況的確存在。', width=600)fig.update_layout(xaxis_title='', yaxis_title='', plot_bgcolor='white', title=dict(font=dict(size=20),xref='paper'), yaxis=dict(showticklabels=False))下面我們把持械名單用詞雲來表示,字體越大的,表示出現次數越多
from wordcloud import WordCloud, ImageColorGeneratorfrom PIL import Imagefrom os import pathimport numpy as np
armed=all_data['armed']words = ''tokens=list()for i in range(len(armed)): words +=' '+str(armed.iloc[i]).strip()wordcloud = WordCloud(width = 1500, height = 800, min_font_size = 16,colormap='Blues').generate(words) plt.figure(figsize=(15,10))plt.imshow(wordcloud)plt.axis("off")前面也提到,數據裡有每個案件發生的經緯度信息,通過把這些事件顯示在地圖上,可以更好幫助我們了解案件發生的信息:
df_all=all_data.dropna(subset=['latitude'])san_map = folium.Map(location=[37.77, -122.42], zoom_start=4,width='100%',height='100%')incidents = folium.map.FeatureGroup()for lat, lng, in zip(df_all.head(1000).latitude, df_all.head(1000).longitude): incidents.add_child( folium.CircleMarker( [lat, lng], radius=2, color='red', fill=True, fill_color='red', fill_opacity=0.6 ) )san_map.add_child(incidents)很明顯,東西兩岸都是高發地,特別是經濟發達的地區,都是高發,來,我們把數據歸到各州看看:
df_st = all_data.groupby('state').agg('count') df_st.reset_index(inplace=True) df=df_st[['state','id','name']]state_geo = f'./us-states.json'm = folium.Map(location=[48, -102], zoom_start=4)folium.Choropleth( geo_data=state_geo, name='choropleth', data=df, columns=['state', 'id'], key_on='feature.id', fill_color='Reds', fill_opacity=0.9, line_opacity=0.2, bins=9, legend_name='Fatal Police Shooting in US 2015.1-2020.9').add_to(m)folium.LayerControl().add_to(m)m這樣比看柱狀圖更加直觀了,加州和德州最多。
除了這種靜態的地圖信息,我們還可以把在地圖上動態地顯示各地的發生數量以及每個人的姓名:
import numpy as npall_data.dropna(subset=['longitude','latitude'],axis=0,inplace= True) from folium import pluginssan_map = folium.Map(location=[np.mean(all_data.latitude), np.mean(all_data.longitude)], zoom_start=4,width='100%',height='100%')incidents = plugins.MarkerCluster().add_to(san_map) for lat, lng, label, in zip(all_data.latitude, all_data.longitude, all_data.name): folium.Marker( location=[lat, lng], icon=None, popup=label, ).add_to(incidents)san_map.add_child(incidents)
最後,我們把各州以及各城市的發生情況放在一個叫樹形圖的圖形裡面,這樣可以動態的看到每個州,各個城市的情況:
df_tree = pd.pivot_table(all_data,index=['state','city'],values=['id'],aggfunc='count')df_tree.reset_index(inplace = True)fig = px.treemap(df_tree, path=['state', 'city'], values='id',color='id',title="<b>各城市發生射殺事件數量的總體樹形圖(2015年1月-2020年9月)</b>")fig在樹形圖裡,面積代表了數量,同時還能體現包含關係。
通過對這份數據的可視化分析,我們至少可以得出的一個結論就是在美國,的確存在警察濫用暴力的情況,而且還非常的嚴重,同時,警察執法時對於不同族裔的選擇性執法情況也是非常明顯的。而在發生地點方面,越是經濟發達,越是族裔多樣化的地區,案件發生越多。