Introduction

The data used in this analysis is titled “Boston Crimes.” The information provided by this data set includes the details of crimes that have been committed from Jan 1, 2023-Dec 29, 2024

Dataset

The 17 column names are: incident_number, offense_code, offense_code_group, offense_description, district, reporting_area, shooting, occurred_on_date, year, month, day_of_week, hour, ucr_part, street, lat, long, location

There are 155,959 rows.
There are 332, 030 NA’s in the data frame; however, offense_description, district, year, month, day_of_week, hour, and street have zero NA’s.

Findings

The following tabs provide detailed information regarding crimes that happened Boston from Jan 1, 2023 to Dec 29, 2024

Tab 1

The bar chart shows the 10 worse districts in the Boston area. D4 covers the South End neighborhood of Boston, along with parts of Back Bay, lower Roxbury, and the Fenway area. B2 covers the neighborhood of Roxbury

df <- read.csv("//apporto.com/dfs/LOYOLA/Users/briely_loyola/Desktop/2023 to date.csv")
library(dplyr)
library(DescTools)
library(ggplot2)
library(data.table)
library(scales)
# count the number of criminal offensives in each district 
DistrictCount <- data.frame(count(df,DISTRICT ))
#compute the values of the top 10
DistrictCount<-DistrictCount[order(DistrictCount$n, decreasing = TRUE),]
result = DistrictCount[1:10,]
# set up a way to label each bar in the bar graph
values = result$n
# create bar graph
ggplot(DistrictCount[1:10,], aes(x =reorder(DISTRICT,-n),y = n ))+
  geom_bar(colour ="darkblue", fill="lightblue", stat = "identity")+
  labs(title = "Number of Crimes in Boston Districts (Top 10)", x = "District", y = "Number of Incidents")+
  theme(plot.title=element_text(hjust = 0.5))+
  geom_text(aes(label = values),vjust= -0.5,color="black")

Tab 2

The stacked bar chart shows the number of crimes per month for the worst 10 districts

df <- read.csv("//apporto.com/dfs/LOYOLA/Users/briely_loyola/Desktop/2023 to date.csv")
head(df)
library(dplyr)
library(DescTools)
library(ggplot2)
library(data.table)
library(scales)
# count the number of criminal offensives in each district 
DistrictCount <- data.frame(count(df,DISTRICT ))
DistrictCount
#compute the values of the top 10
DistrictCount<-DistrictCount[order(DistrictCount$n, decreasing = TRUE),]
result = DistrictCount[1:10,]
df_reasons <-count(df, DISTRICT)
head(df_reasons)
df_reasons <- df_reasons[order(df_reasons$n,decreasing = TRUE),]
top_reasons <- df_reasons$DISTRICT[1:10]
top_reasons
new_df <- df %>% 
  filter(DISTRICT %in% top_reasons)%>%
  select(MONTH,DISTRICT)%>%
  group_by(DISTRICT,MONTH)%>%
  summarise(n=length(DISTRICT),.groups = 'keep')%>%
  data.frame()
head(new_df)
agg_tot <-new_df %>%
  select(DISTRICT,n) %>%
  group_by(DISTRICT) %>%
  summarise(tot = sum(n),.groups = 'keep')%>%
  data.frame()
agg_tot
library(RColorBrewer)
library(ggthemes) 
library(plyr)
str(new_df)
new_df$MONTH<-as.factor(new_df$MONTH)
ggplot(new_df, aes(x = reorder(DISTRICT,n,sum), y =n,fill = MONTH ))+
  geom_bar(stat="identity")+
  coord_flip()+
  labs(title="Number of Crimes by Districts in Boston", x="Districts in Boston", y = "Number of Crimes")+
  theme_light()+
  theme(plot.title=element_text(hjust=0.5))+
  scale_fill_brewer(palette = "Paired")+
  geom_text(data=agg_tot, aes(x=DISTRICT,y = tot, label=tot, fill=NULL),hjust=-0.1)+
  scale_y_continuous(labels=comma, limits = c(0,25000))
  

Tab 3

Shows the number of crimes per hour

df <- read.csv("//apporto.com/dfs/LOYOLA/Users/briely_loyola/Desktop/2023 to date.csv")
#check to make sure the data file is correct

library(dplyr)
library(ggplot2)
library(scales)
library(ggthemes)
library(ggrepel)
hours_df<-df %>%
  select(HOUR) %>%
  group_by(HOUR) %>%
  summarise(n = length(HOUR), .groups ='keep') %>%
  data.frame()
#check to make sure data is correct
#check to make sure hour is an integer
#str(hours_df)
x_axis_labels = min(hours_df$HOUR):max(hours_df$HOUR)

hi_lo <- hours_df %>%
  filter(n == min(n) | n == max(n)) %>%
  data.frame()

ggplot(hours_df, aes(x =HOUR, y = n))+
  geom_line(color = 'black', linewidth =1)+
  geom_point(shape =21, size=4, color = 'red', fill = 'white')+
  labs(x ="Hour",y = "Number of Crimes", title="Number of Crimes by Hour", caption="Source: Boston Crime Data")+
  scale_y_continuous(labels=comma)+
  theme_light()+
  theme(plot.title=element_text(hjust = 0.5))+
  scale_x_continuous(labels=x_axis_labels, breaks=x_axis_labels,minor_breaks=NULL)+
  geom_point(data = hours_df %>% filter(HOUR == 23), aes(x = HOUR, y = n), shape = 21, size = 4, fill = 'red', color = 'red') +
  geom_point(data= hi_lo,aes(x =HOUR, y = n), shape =21, size =4, fill = 'red',color = 'red')+
  geom_label_repel(aes(label =  ifelse(n==max(n) | n==min(n)|HOUR == max(HOUR), scales::comma(n), "")), 
                   box.padding = 2,
                   point.padding = 1, 
                   size = 4, 
                   color='Grey50',
                   segment.color='darkblue')

### Tab 4

This chart shows the number of crimes per month and for each month, it shows the number of crimes per day.

df <- read.csv("//apporto.com/dfs/LOYOLA/Users/briely_loyola/Desktop/2023 to date.csv")
#check to make sure the data file is correct
head(df)
##   INCIDENT_NUMBER OFFENSE_CODE OFFENSE_CODE_GROUP  OFFENSE_DESCRIPTION DISTRICT
## 1       232007173         3115                 NA   INVESTIGATE PERSON       B3
## 2       232004454         3301                 NA       VERBAL DISPUTE       B2
## 3       232006290         3115                 NA   INVESTIGATE PERSON       A1
## 4       232024939         3114                 NA INVESTIGATE PROPERTY       B3
## 5       232006708          423                 NA ASSAULT - AGGRAVATED       B2
## 6       232007629         3115                 NA   INVESTIGATE PERSON       E5
##   REPORTING_AREA SHOOTING       OCCURRED_ON_DATE YEAR MONTH DAY_OF_WEEK HOUR
## 1                       0 2023-01-27 22:44:00+00 2023     1   Friday      22
## 2            316        0 2023-01-17 20:21:00+00 2023     1   Tuesday     20
## 3                       0 2023-01-24 00:00:00+00 2023     1   Tuesday      0
## 4                       0 2023-03-31 17:14:00+00 2023     3   Friday      17
## 5                       0 2023-01-26 09:00:00+00 2023     1   Thursday     9
## 6            681        0 2023-01-29 14:55:00+00 2023     1   Sunday      14
##   UCR_PART                                               STREET      Lat
## 1       NA                                             FAVRE ST 42.27166
## 2       NA                                            HAROLD ST 42.31260
## 3       NA                                           HANOVER ST 42.36570
## 4       NA                                        BLUE HILL AVE 42.29279
## 5       NA                                         HUTCHINGS ST 42.31027
## 6       NA WASHINGTON ST & METROPOLITAN AVE\nBOSTON  MA 02131\n 42.28141
##        Long                                 Location
## 1 -71.09953 (42.271661031027065, -71.09953455161765)
## 2 -71.09288   (42.3125962960786, -71.09287583752645)
## 3 -71.05289   (42.3656993584582, -71.05289203191269)
## 4 -71.08852  (42.29278799134922, -71.08851953962399)
## 5 -71.08931 (42.310268910354935, -71.08931055058088)
## 6 -71.13355  (42.28140997944129, -71.13355001769462)
library(dplyr)
library(ggplot2)
colnames(df)
##  [1] "INCIDENT_NUMBER"     "OFFENSE_CODE"        "OFFENSE_CODE_GROUP" 
##  [4] "OFFENSE_DESCRIPTION" "DISTRICT"            "REPORTING_AREA"     
##  [7] "SHOOTING"            "OCCURRED_ON_DATE"    "YEAR"               
## [10] "MONTH"               "DAY_OF_WEEK"         "HOUR"               
## [13] "UCR_PART"            "STREET"              "Lat"                
## [16] "Long"                "Location"
library(scales)
library(ggthemes)
library(RColorBrewer)
# change numbers 1,2, etc to January, February, etc
df$month_name <- month.name[df$MONTH]
#head(df$month_name)
days_df <- df %>%
  select(month_name, DAY_OF_WEEK) %>%
  group_by(month_name, DAY_OF_WEEK) %>%
  summarise(n = length(DAY_OF_WEEK), .groups = 'keep') %>%
  data.frame()
#head(days_df)

ggplot(days_df, aes(x=DAY_OF_WEEK, y=n, fill=month_name)) +
  geom_bar(stat="identity", position = "dodge") +
  theme_light() + 
  theme(plot.title = element_text(hjust=0.5)) +
  scale_y_continuous(labels=comma) +
  labs (title = "Multiple Bar Charts -Total Crimes by Month and by Day", 
        x = "Day of the Week", 
        y = "Number of Crimes",
        fill = "month_name")+
  scale_fill_brewer(palette = "Paired") +
  facet_wrap(~month_name,ncol=4,nrow = 3)+
  #need to have days shown vertical and not horizontal 
  theme(axis.text.x=element_text(angle=90, size=8))

Tab 5

This chart shows the percentage of shooting per day

# change numbers 1,2, etc to January, February, etc
df$month_name <- month.name[df$MONTH]
#head(df$month_name)
days_df <- df %>%
  select(month_name, DAY_OF_WEEK) %>%
  group_by(month_name, DAY_OF_WEEK) %>%
  summarise(n = length(DAY_OF_WEEK), .groups = 'keep') %>%
  data.frame()
#head(days_df)

ggplot(days_df, aes(x=DAY_OF_WEEK, y=n, fill=month_name)) +
  geom_bar(stat="identity", position = "dodge") +
  theme_light() + 
  theme(plot.title = element_text(hjust=0.5)) +
  scale_y_continuous(labels=comma) +
  labs (title = "Multiple Bar Charts -Total Crimes by Month and by Day", 
        x = "Day of the Week", 
        y = "Number of Crimes",
        fill = "month_name")+
  scale_fill_brewer(palette = "Paired") +
  facet_wrap(~month_name,ncol=4,nrow = 3)+
  #need to have days shown vertical and not horizontal 
  theme(axis.text.x=element_text(angle=90, size=8))

Conclusion

The findings of this analysis provide a detailed evaluation of the crimes that have occurred in Boston from Jan 1, 2023 to Dec 29, 2024. The first tab depicts the worse 10 districts in Boston. The worse district was D4, which covers the South End neighborhood of Boston, along with parts of Back Bay, lower Roxbury, and the Fenway area. The second worse district was B2, which covers the neighborhood of Roxbury. This shows people should be cautious when entering the neighborhood of Roxbury. The second tab further looks at the number of crimes committed in the worse 10 districts in Boston per month. No month really stands out. Tab three shows the number of crimes per hour. The worse is around midnight. The safest time is between 3am to 6 am. Tab 4 depicts the total crimes buy month and day. No particle day stands out for every month, but there is a trend that Fridays are the worse. Tab 5 shows the number of crimes involving a gun per day. Although the percentage are low, Saturday and Sunday are the worse (1%) and Wednesday has the lowest percentage (0.5%) This analysis provides information on where the worse crimes are committed, the days of the month where the worse crimes are committed and the worse times and safest times for crimes. This information should be useful for someone planning a trip to Boston