Friday, 4 October 2019

Police UK API: Local crime data with Gambas

In the UK our Police force have recently made crime data available via the net.


You can access monthly crime figures by category from their website.


But there is also a simple API available for you to carry out your own data analysis.

The website only allows you to view crimes for a given area by selecting a year and month. As some months may be more 'active' than others, I thought it would be more useful to see crimes committed for a whole year.

As we are currently considering moving house to a new area, checking the crime figures may be useful when comparing one area to another.

Full details of the a.p.i. are here: https://data.police.uk/docs/

At the moment I'm just using one command to get 'street level crimes' which just requires coordinates (latitude & longitude), year and month. So if you type this string into a web browser:-

https://data.police.uk/api/crimes-street/all-crime?lat=51.0676687&lng=-0.3270352&date=2018-12

...or this into a terminal:-

curl 'https://data.police.uk/api/crimes-street/all-crime?lat=51.0676687&lng=-0.3270352&date=2018-12'

...you should get back details of crimes recorded in Horsham during December 2018, in JSON format.

some Gambas code


To request, read and decode the JSON data I wrote some code like this:-

Public allCategoriesMonth As New String[]     'crime categories
Public allMonthlyCatCounts As New Integer[]   'crime counts by category
 
Public Sub GetData()

Dim strData As String   'the returned Json report
Dim index As Integer
Dim colCrimes As JSONCollection[]   'the whole report as a collection

Dim colCrimeRow As JSONCollection  'individual crimes records/collections
Dim blnCategoryExists As Boolean

 Shell "curl 'https://data.police.uk/api/crimes-street/all-crime?lat=51.0676687&lng=-0.3270352&date=2017-02'" To strData

    colCrimes = JSON.Decode(strData, True)
    txtCrimeCount.Text = colCrimes.Length
   
    For Each colCrimeRow In colCrimes
      blnCategoryExists = False
      If allCategoriesMonth.Count > 0 Then 'check this category against any logged so far
        For index = 0 To allCategoriesMonth.Max
          If colCrimeRow["category"] = allCategoriesMonth[index] Then
            blnCategoryExists = True
            Inc allMonthlyCatCounts[index]   'update total
          Endif 
        Next
        If Not blnCategoryExists Then  'if a new category, add to array
          allCategoriesMonth.Add(colCrimeRow["category"])
          allMonthlyCatCounts.Add(1)
        Endif      
      Else  'no categories, so create 1st one
        allCategoriesMonth.Add(colCrimeRow["category"])
        allMonthlyCatCounts.Add(1)
      Endif
    Next


...then display data


I displayed the resulting crime data in a grid.

getting coordinates


Clearly its a bit of hassle having to provide this program with Lat/Long coordinates, so I did a search for a free geocoding api. Offerings from Google & Bing required a "Billing Address" ...no thanks mate!

A few genuinely free apis had terms... that would have taken me until 2030 to read (I plan to stop coding long before then). Eventually I found this one from the DataScienceToolkit:-
 http://www.datasciencetoolkit.org/developerdocs#street2coordinates

Not only is this free, but you don't even need an api key.

I'm using a command like this:-

curl 'http://www.datasciencetoolkit.org/street2coordinates/Middle+Wallop%2c+United+Kingdom'


...which returns Lat/Lng for Middle Wallop, UK
...and where "+" is used in place of a space, and "%2c" = a comma

The Gambas code looks something like this:-

Public Sub btnGetCoords_Click()
Dim strTownOrCode As String
Dim strJsonData As String
Dim colGeocode As JSONCollection
Dim colLocation As JSONCollection

  Me.Mouse = Mouse.Wait
  Wait
  If txtTownPostCode.Text <> "" Then
    strTownOrCode = Replace(txtTownPostCode.Text, " ", "+")
    strTownOrCode = LOOK_UP & UCase(strTownOrCode) & "%2c+United+Kingdom"
 
    Shell "curl " & strTownOrCode To strJsonData
 
    colGeocode = JSON.Decode(strJsonData, True)
    For Each colLocation In colGeocode
      txtLat.Text = colLocation["latitude"]
      txtLong.Text = colLocation["longitude"]
    Next
  Endif

...display lat/long...
   
Catch
  lblStatus.Text = Error.Text
End


...which will accept either the name of the village/town/city or the post code.

So with a bit more coding, my application UI looks like this:-



So far, so good!

It probably now needs some kind of 'crimes per capita' indication.



No comments:

Post a Comment