!pip install folium
import folium
import requests
import pandas
import re
arrest_table = pandas.read_csv("https://cmsc320.github.io/files/BPD_Arrests.csv")
arrest_table = arrest_table[pandas.notnull(arrest_table["Location 1"])]
arrest_table["lat"], arrest_table["long"] = arrest_table["Location 1"].str.split(",").str
arrest_table["lat"] = arrest_table["lat"].str.replace("(", "").astype(float)
arrest_table["long"] = arrest_table["long"].str.replace(")", "").astype(float)
Requirement already satisfied: folium in /opt/conda/lib/python3.8/site-packages (0.12.1) Requirement already satisfied: requests in /opt/conda/lib/python3.8/site-packages (from folium) (2.25.1) Requirement already satisfied: jinja2>=2.9 in /opt/conda/lib/python3.8/site-packages (from folium) (2.11.2) Requirement already satisfied: branca>=0.3.0 in /opt/conda/lib/python3.8/site-packages (from folium) (0.4.2) Requirement already satisfied: numpy in /opt/conda/lib/python3.8/site-packages (from folium) (1.19.5) Requirement already satisfied: MarkupSafe>=0.23 in /opt/conda/lib/python3.8/site-packages (from jinja2>=2.9->folium) (1.1.1) Requirement already satisfied: urllib3<1.27,>=1.21.1 in /opt/conda/lib/python3.8/site-packages (from requests->folium) (1.26.2) Requirement already satisfied: chardet<5,>=3.0.2 in /opt/conda/lib/python3.8/site-packages (from requests->folium) (4.0.0) Requirement already satisfied: certifi>=2017.4.17 in /opt/conda/lib/python3.8/site-packages (from requests->folium) (2020.12.5) Requirement already satisfied: idna<3,>=2.5 in /opt/conda/lib/python3.8/site-packages (from requests->folium) (2.10)
<ipython-input-1-a65f07558412>:11: FutureWarning: Columnar iteration over characters will be deprecated in future releases. arrest_table["lat"], arrest_table["long"] = arrest_table["Location 1"].str.split(",").str
arrest_table.head()
arrest | age | race | sex | arrestDate | arrestTime | arrestLocation | incidentOffense | incidentLocation | charge | chargeDescription | district | post | neighborhood | Location 1 | lat | long | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 11127013.0 | 37 | B | M | 01/01/2011 | 00:01:00 | 2000 Wilkens Ave | 79-Other | Wilkens Av & S Payson St | 1 1425 | Reckless Endangerment || Hand Gun Violation | SOUTHERN | 934.0 | Carrollton Ridge | (39.2814026274, -76.6483635135) | 39.281403 | -76.648364 |
2 | 11126887.0 | 46 | B | M | 01/01/2011 | 00:01:00 | 2800 Mayfield Ave | Unknown Offense | NaN | NaN | Unknown Charge | NORTHEASTERN | 415.0 | Belair-Edison | (39.3227699160, -76.5735750473) | 39.322770 | -76.573575 |
3 | 11126873.0 | 50 | B | M | 01/01/2011 | 00:04:00 | 2100 Ashburton St | 79-Other | 2100 Ashburton St | 1 1106 | Reg Firearm:Illegal Possession || Hgv | WESTERN | 735.0 | Panway/Braddish Avenue | (39.3117196723, -76.6623546313) | 39.311720 | -76.662355 |
4 | 11126968.0 | 33 | B | M | 01/01/2011 | 00:05:00 | 4000 Wilsby Ave | Unknown Offense | 1700 Aliceanna St | NaN | Unknown Charge | NORTHERN | 525.0 | Pen Lucy | (39.3382885254, -76.6045667070) | 39.338289 | -76.604567 |
5 | 11127041.0 | 41 | B | M | 01/01/2011 | 00:05:00 | 2900 Spellman Rd | 81-Recovered Property | 2900 Spelman Rd | 1 1425 | Reckless Endangerment || Handgun Violation | SOUTHERN | 924.0 | Cherry Hill | (39.2449886230, -76.6273582432) | 39.244989 | -76.627358 |
date = "01/01/2011"
# arrest_table data only from a specific date
df = arrest_table.loc[arrest_table["arrestDate"] == date]
# list of types of offenses for that day, used for deciding which to highlight
df.incidentOffense.drop_duplicates()
1 79-Other 2 Unknown Offense 5 81-Recovered Property 9 54-Armed Person 13 20A-Followup 21 4E-Common Assault 23 87-Narcotics 25 4B-Agg. Asslt.- Cut 26 75-Destruct. Of Property 31 55-Disorderly Person 38 4C-Agg. Asslt.- Oth. 46 4D-Agg. Asslt.- Hand 52 6D-Larceny- From Auto 65 5A-Burg. Res. (Force) 67 111-Protective Order 87 24-Towed Vehicle 96 87O-Narcotics (Outside) Name: incidentOffense, dtype: object
# creates the map
map_osm = folium.Map(location=[39.29, -76.61], zoom_start=11)
# loops through each entry in the dataframe, adds a marker for each
for row in df.iterrows():
curr = row[1]
# hover info, color and icon
if curr.incidentOffense == "Unknown Offense":
tooltip = "Unknown Offense"
color="lightgray"
icon = "question-sign"
else:
offense = curr.incidentOffense.split("-", 1)
tooltip = offense[1]
if re.match("^4\D?$", offense[0]): # assault
color = "red"
elif re.match("^5\D?$", offense[0]): # burgulary
color = "lightred"
elif re.match("^6\D?$", offense[0]): # larceny
color = "blue"
elif offense[0] == "54": # armed person
color = "black"
elif re.match("^87\D?$", offense[0]): # narcotics
color = "green"
elif offense[0] == "75": # desctruction of property
color = "orange"
elif offense[0] == "79": # other
color = "cadetblue"
else: # anything else
color = "darkblue"
icon = "exclamation-sign"
icon=folium.Icon(color=color, icon=icon)
# info on click
popup = "ID: " + str(curr.arrest) + \
"\nTime: " + curr.arrestTime + \
"\nAge: " + str(curr.age) + \
"\nRace: " + curr.race + \
"\nSex: " + curr.sex
# adds marker
folium.Marker([curr.lat, curr.long], tooltip=tooltip, popup=popup, icon=icon).add_to(map_osm)
map_osm
This map shows the locations of criminal offenses that occur in Baltimore on a given day; in this case, January 1st, 2011. The color of each marker represents the type of offense that it represents, which is labeled more specifically when hovering over a marker. By clicking on a marker you can see more information: ID, the time that the offense occured, and the age and race of the offender.
I chose this representation of the data for two reasons. It makes it easy to get a lot of information at a glance, such as a ballpark of how many total offenses were commited on that day, how many offenses of each color-type were commited, and where they occured. It can also show more information than just a static image would be able to when clicking on the markers. Because the database contains a lot of data, it didn't make sense to add markers for every offense logged, so I decided to set a time window of one day. By changing the date
string near the beginning of this notebook you can change the day it shows, and compare data across days. For example when I put in "12/25/2011"
for Christmas 2011 I see a high number of offenses logged compared to other days, a large proportion of which are classified as narcotics—represented by green markers.