Visualising spending behaviour through open banking and GIS
By: Michael Parker
Tags: Data Visualization, Banking, Analytics, Maps, Data Science

Financial habits have historically been something that people place back of mind, but with the rising amount of information and tools available, a new attitude to financial control is creating a rising popularity in transparent, digital banking. A new breed of financial institutions (such as Monzo, Starling, Revolut and N26) are leveraging digital products to enable their customers to have greater access and control of their spending. They achieve this by offering modern mobile applications, real-time notifications, better security, and developer APIs that allow previously inaccessible to be available for analysis and productisation by anyone with an idea.

Technology has also aided human behaviour in other ways. When people think about an event or memory they often refer to where it occurred. When trying to find a photo on a phone it’s often easier to describe where it occurred rather than the date it was taken e.g. “We were in Spain” or “it was at my home in Greenwich”. The same human behaviours can be applied to financial decisions and spending. A statement reading “-£82.00 at XDB Goods” doesn’t help explain the story and decisions behind the transaction, leaving people confused and desperately trying to think of what it could be.

I’m interested in exploring the representation of financial transactions on a map to help answer questions about where spending occurs and trigger memories about places visited. This map combined with other data layers can also be used to recognise and identify historic spending habits, find new places to visit, or even identify fraudulent and unusual transactions through location.

Data size and scope

For this experiment, I used Monzo, who provide a very comprehensive API to extract information about users on their platform. Collecting this data requires very explicit consent to gather and store the data, so for this exercise I have only used my own data although it is possible to build a scalable application and analyse the data from other users with their permission.

The dataset contains every transaction on my personal current account for the last 3 years, at just over 5000 records. The data is formatted as JSON and structured as an array of objects with each transaction containing the timestamp, amount as an integer of pence/cents, currency, description, category, notes, attachments (such as receipts), metadata, information about settlement, and merchant information. The merchant information contains the name, co-ordinates, address, Google Places ID, country and an approximate flag (to mark when a merchant location is estimated).

Initial analysis

The dataset presented an exciting opportunity to find and analyse more about my spending habits and also better understand the capabilities of the Monzo API. I created a JavaScript program to parse through the transactions and do some very basic topical categorisation.

In the dataset I found about 1/3 of the transactions were spent on eating out and 1/3 of those just on coffee. Cafés represented over 400+ transactions but overall was a relatively low spend, averaging just over £3.5 each visit. The largest transaction by amount were work expenses, the most expensive personal purchases being shopping, and an extreme outlier at almost 5x the next highest transaction amount on pre-paid flight lessons for a pilot licence I completed last year. The majority of transactions occur in London but they spread across 5 continents with the most isolated transactions occurring in Hobart, Tasmania.

Figure 1: All global transactions weighted by amount

The total amount of money moving through the account over the three-year period came to a staggering ~£200k (which includes business expenses and transfers to other banks) and ~£90k including only personal expenses. Monzo isn’t my only bank and the stark difference between these numbers is illustrative of the complications of using the data raw to draw meaningful conclusions. Business expenses are not indicative of personal financial habits and could very easily skew the visualisation; to ensure an accurate and informative map the data requires sanitisation.

Initial experiments

To get an understanding of what could be possible using this dataset and also understand the limitations and opportunities that the mapping software QGIS could offer I loaded in a base map from MapBox and imported all 5000 transactions.

The software was slow to render and the points were all overlapping. Even when allocating the transactions different colours for each category, the map wasn’t useful or easy to draw anything meaningful from. Having too much information meant items were overlapping and didn’t present the useful conclusions as I had initially hoped.

Figure 2: All transactions layered on a base map with equal weighting

Presenting the transaction this way did let me find interesting outliers and complications with the dataset that I wouldn’t have noticed without doing this experiment. Online purchases were particularly problematic with location (for example, AWS shows as the geographical centre of the USA). This was also true for merchants where Google didn’t know their physical address and placed the merchant in the geographical centre of the country.

The default centre of London is Trafalgar Square, where there are no shops so it’s safe to say these merchant locations are inaccurate.

Sanitising the dataset

I modified the JavaScript application to iterate over the transactions and perform some filtering and normalising. Firstly, any transaction categorised as Expenses, Bills, Finances, and Deposits would be removed leaving only personal expenses. I also removed any transactions where the merchant didn’t exist or where there wasn’t geo-information available. I also renamed some of the keys to make the data easier to work with in and flattened the JSON structure to make it easier to convert to CSV. This created a file containing only transactions that occurred in a physical merchant and that were not business expenses called `Monzo Sanitised Transactions`.

Figure 3: The node app iterates over the dataset and writes a CSV file containing the location data

To make the data even easier to experiment with I also created a subset of the data containing only eating out transactions (called `Monzo Eating Out`). This smaller dataset resolved some of the performance issues I was facing with QGIS.

I wanted to reflect the value of the transaction in the visualisation using the size parameter of the map marker. Another problem I faced was that all the transaction amounts were mostly negative (as these represent transactions where money is leaving the account). The mapping software QGIS requires a positive integer scale, so I modified the amount value by adjusting the sanitising formula to multiply the transaction amount by -1. One consequence this had is now refunds have a negative value; to solve this, I limited the minimum represented value to zero ensuring only debited transactions are shown.