Beginner exercise: “How can we use several factors such as income, location, and voting stats to predict hate crime rates?”
By: Marco Valenzuela
Tags: Data Visualization, Pycharm, Learning To Code, Jupyter Notebook, Data Analysis

The objective of this project was to learn some key Python skills as well as apply some previously learnt and refreshed skills on Data Analysis. The question was one of my own choice as well as the data set. I got the data from GitHub: https://github.com/fivethirtyeight/data/blob/master/hate-crimes/hate_crimes.csv

The data was comprised of 51 different data points, corresponding to American states, each data point had 12 different entries:

State: In another analysis it might have been useful to split the states into region say, be that some arbitrarily chosen factor variable such as “east coast, west coast” etc, or perhaps the latitude and longitude as a numerical variable.

Hate crimes per 100k “splc” and “Average hate crimes per 100k FBI”: these are both from reputable sources, so choosing one is a matter of preference. However, using them as predictors is not very useful, so one of them had to go: I decided to keep FBI as it is a more commonly known organization and it was alphabetically first. It would have been equally valid to choose splc.

The rest all seemed like they could be relevant: Median Household Income, Share of unemployed seasonal, Share of population in metropolitan areas, Share of population with high school degree, Share of non-citizens living in the area, share of white poverty, GINI index, share of non white and share of voters who voted for Trump. All of the data types were numerical variables rather than factor (excluding the variable I added for the violin plot, a Boolean based on Median Household income)

These stats are from around 2015–2016, depending on the statistic and if interested one can read some more detail on them here: https://github.com/fivethirtyeight/data/blob/master/hate-crimes/README.md.

Now to better understand the data, we present some basic facts about it as well as some graphs, the first being the set of pair plots. This is quite messy as there are lots of data points fitted into a small space, but we can look past the mess and find out lots of important pieces of information:

Specifically if we look on the diagonal we can have some idea on the distribution of some of these variables, as well as be able to spot any correlations between predictor variables to later remove one of them from the model.

Lets say we were specifically interested in the stat: median income. I created an extra column which was a Boolean which stated whether or not a States Median income was above or below the mean Median income: using this I created a Box plot and Violin plot:

We see that being above the median seems to increase the amount of hate crimes, but we could see this from the pair plot: whats new here is the change in distribution between states which are above median and states which are below. There is also the anomalous result, for future I should find the Cooks distance of this one result.

Now we want to create a model to answer the question: the model I chose was a linear regression model: this assumes a linear relationship between the input variables and the single output variable (in our case the FBI hate crime rate).

We first build our model by splitting the data into a response matrix and a vector of targets. We then set aside 20% of the data to test our model after we have built it and choose the random seed of 42 to be able to replicate the results.

We use the LinearRegression() object and the .fit function to create our model, and then use our model to make a prediction on Y given our X_hc_test, which allows us to “score” how well our model did, by comparing it to the previous results.

Now that we have our predictions we can test the remaining assumptions using the residuals. We are going to use an ACF plot to see if there are any patterns in the residuals

The code for producing the ACF plot

Since the ACF plot decays to 0 at the first lag, we conclude there is no auto correlation. Otherwise, we would have to do some time series, but we are in the clear. The next assumption we need to check is for homoscedasticity: “if the variance of the residuals is non-constant then the residual variance is said to be ‘heteroscedastic’ ”.

Since the variance of the residuals is non constant, our assumption holds and we can continue. Finally, we have our model and our predictions, we checked all the assumptions we needed to, and now it remains to see how good our model is. So to evaluate our model we finally use the “test data” and quantify how far off our predictions are:

What the r² score represents is how much better our model is than predicting with just a straight line, the 0.059 shows us that our model is not much better than a straight line. This is odd considering some of the data points we have: median income, percentage of trump supporters, etc. An obvious way that anyone could come up with to improve the model would be to gather more data: this could be different states from different countries, perhaps Canada and European countries have similar enough characteristics to match and add more points. One could also have more variables, but the idea that I would be most interested in viewing is using a model which takes in non linear inputs as predictors, i.e. use a model that is more complex than linear regression.

Overall I would say that my work in creating a model fell flat on its face, though considering I knew null about Python going into this project I am quite happy with some of the understanding about coding and stats I have gained from it.