The Art of Geofencing in Python

Tutorial — Triggering notifications and Nudging GPS locations from users.

Geofencing example from Mapbox: London congestion — Source

Geofencing is often used tool in Geographic data science, especially in marketing, security and zoning applications. The example in the above GIF shows an app that alerts vehicles based on their location and London’s Congestion Charge Zone (CCZ). The application calculates the congestion charge and tracks the number of vehicles inside the congestion area at a given time.

The concept of geofencing is straightforward, yet it is a powerful technique that enhances location applications. Simply put, a geofence is a defining virtual boundary around geographic objects or an area, so that every time a user enters or leaves the boundary perimeters, actions or notifications can be triggered. With the increased use of smartphones, GPS, and location services, geofencing becomes an indispensable tool in location data analytics and intelligence.

In this tutorial, we use a GPS Trajectory dataset. It contains GPS
points (latitude and longitude) with timestamps. It also provides unique track_id for each trajectory. Let us read the data with the Pandas library.

import pandas as pd
import geopandas as gpd
import plotly_express as px
import matplotlib.pyplot as plt
!wget https://www.dropbox.com/s/ejev7z29lzirbo5/GPSTrajectory.zip
!unzip GPSTrajectory.zip
df = pd.read_csv(‘GPSTrajectory/go_track_trackspoints.csv’)
df.head()

The first five rows of the dataset are shown below. We have latitude and longitude as well as track_id and time.

Geofencing example from Mapbox: London congestion — Source

We convert the Dataframe into Geodataframe, which allows us to perform geofencing. Converting the data frame to Geodataframe with Geopandas is straightforward.

gdf = gpd.GeoDataFrame( df, geometry=gpd.points_from_xy(df.longitude, df.latitude))
gdf.head()

Let us plot a map of the dataset. We use Plotly Express here as offers an easy interface and high-level API for plotting with Plotly. We need to set Mapbox token here.

px.set_mapbox_access_token(“pk.eyJ1Ijoic2hha2Fzb20iLCJhIjoiY2plMWg1NGFpMXZ5NjJxbjhlM2ttN3AwbiJ9.RtGYHmreKiyBfHuElgYq_w”)
px.scatter_mapbox(gdf, lat=”latitude”, lon=”longitude” ,size_max=6, zoom=8, width=1200, height=800)

The plot below shows all the points in the dataset. As you can see, these trajectories fall in 3 different cities.

Geofencing example from Mapbox: London congestion — Source

Let us filter out other cities and focus on the central city(Aracuja) since most of the data fall here.

gdf = df[(gdf[‘latitude’]<-10.80) & (gdf[‘longitude’]>-37.5)]
px.scatter_mapbox(gdf, lat=”latitude”, lon=”longitude” ,size_max=6, zoom=8, width=1200, height=800)

Now we have only points that we are interested in Aracuja city, Brazil.

Geofencing example from Mapbox: London congestion — Source

Now that we have cleaned the data let us do geofencing.

Geofencing

First, we need to have an area that marks the geofence. Let us download an area that I have created which is in the city centre.

# Get the data
!wget https://www.dropbox.com/s/e9g5n7e7iwnue4x/CENTERAREA.zip
!unzip CENTERAREA.zip
polygon = gpd.read_file(“CENTERAREA.geojson”)

Let us plot the polygon with Geopandas and overlay the points to see both data.

# Plot track_id 1 points over the Buffer Polygon
fig, ax = plt.subplots(figsize=(10,10))
gdf.plot(ax=ax, color=’black’)
polygon.plot(ax=ax)
#plt.tight_layout()
#plt.axis(‘off’)
plt.show()

Here is the map overlaying both the polygon and points data, shown below.

Geofencing example from Mapbox: London congestion — Source

Now, let us perform what we call Point in Polygon (PIP). We can use “within” operation in Geopandas to check whether the points are inside the polygon or not.

mask = (polygon.loc[0, ‘geometry’])
pip_mask_geofence = gdf.within(mask)

The above code will return a series of False and True values depending on whether the point is inside the polygon or not. Let us add a column to our data that marks False and True values. We call this “geofence”.

#Create PIP mask
gdf.loc[:,’geofence’] = pip_mask_geofence
gdf.sample(5)

Now, our data has a “geofence” column. Let us look at a sample of the data.

Geofencing example from Mapbox: London congestion — Source

As you can see, there is addition column in the data: geofence. The first four rows show that they are not inside the geofence, while the last row indicates that it is inside the geofence. Let us replace False and True values with In and Out values, respectively.

# Replace True with In and False with Out
gdf[‘geofence’] = gdf[‘geofence’].replace({True: ‘In’, False: ‘Out’})

We can see now if we plot a map with Plotly Express and use geofence as a colour, which points are inside or outside the geofencing area.

px.scatter_mapbox(gdf, lat=”latitude”, lon=”longitude”, color=”geofence”, size=’track_id’ ,
size_max=6, zoom=12, width=1200, height=800)
Geofencing example from Mapbox: London congestion — Source

Finally, we can animate the points to visualize with track movements. The annimation can be accomplished easily with Plotly Express. However, it can not visualize all our points at one time due to some limitations. Let us visualize one Track ID now.

px.scatter_mapbox(gdf[gdf[“track_id”]== 23], lat=”latitude”, lon=”longitude”, color=”geofence”, size=’track_id’, animation_frame=’time’, size_max=10, zoom=12, width=1200, height=800)

Here is GIF animation of our simple Geofencing example. Once the track gets inside the geofence area, the points become red, while being blue outside of the marked area.

Geofencing example from Mapbox: London congestion — Source

Conclusion

In this tutorial, we have seen how to do a simple Geofencing example with Python using Pandas, Geopandas and Plotly Express. If you want to experiment with the code, here is the link to Google Colab Notebook.

Leave a Reply

Your email address will not be published. Required fields are marked *