Skip to content

Commit 12d725c

Browse files
committed
Add documentation
1 parent ada634f commit 12d725c

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This repository contains a simple implementation of a time-space clustering model implemented as a [jupyter](http://jupyter.org/) notebook. See the notebook for more information.

simple-time-space-clustering.ipynb

+25-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
{
22
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"In this notebook we propose a method to efficiently cluster time-space data using the existing DBSCAN implementation in [scikit-learn](http://scikit-learn.org/). Before taking this approach, we considered two other approaches to time-space clustering. The first was to use an [existing implementation](https://github.com/eubr-bigsea/py-st-dbscan) of [ST-DBSCAN](http://www.sciencedirect.com/science/article/pii/S0169023X06000218). This implementation uses [COMPSS](https://www.bsc.es/research-and-development/software-and-apps/software-list/comp-superscalar/) for distributed computing, which may be nontrivial to quickly deploy. The second approach that we considered was to implement a custom time-space metric in python which we could pass into the scikit-learn DBSCAN implementation. However, we were concerned that this approach would not scale very well to large data sets compared to metrics predefined (and optimized) in scikit-learn.\n",
8+
"\n",
9+
"Our approach is to precompute a sparse spatial distance matrix where a given pairwise distance is only included if the time-distance is smaller than a given threshold. That is, for pairs of data points, we do the following:\n",
10+
"\n",
11+
"1. If the time distance is smaller than a given threshold value, and\n",
12+
"2. If the space distance is smaller than a second given threshold, then\n",
13+
"3. Include the space distance in the sparse pairwise distance matrix\n",
14+
"\n",
15+
"One way to think of this approach is that we are defining a time-space metric in which the time component only takes two values: smaller-than-epsilon and infinity.\n",
16+
"\n",
17+
"If the input data set is sorted by timestamp, then computing this distance matrix can be very efficient because you only ever need to compare pairs of points that are physically near each other in the data. In fact, it may be possible to modify this approach to apply and record a custom time-space metric (i.e., to try the second approach that we rejected for scaling badly when directly supplied to the DBSCAN implementation).\n",
18+
"\n",
19+
"Compared to ST-DBSCAN, this approach incorporates the time-distance in a very crude way and we expect the results will reflect that."
20+
]
21+
},
322
{
423
"cell_type": "code",
524
"execution_count": null,
@@ -30,7 +49,7 @@
3049
},
3150
"outputs": [],
3251
"source": [
33-
"# In this cell we define the function used to compute the sparse distance matrix\n",
52+
"# Define the function used to compute the sparse distance matrix\n",
3453
"\n",
3554
"\"\"\"Return the index of the first element x in a collection such that pred(x) is True.\"\"\"\n",
3655
"def find(coll, pred):\n",
@@ -69,11 +88,12 @@
6988
" space_window = collections.deque() # [lat, long]\n",
7089
" \n",
7190
" for row in rr:\n",
72-
" lat, long, current_ts = row['lat'], row['lon'], row['date']\n",
91+
" lat, long, current_ts = row['lat'], row['lon'], row['date'] \n",
92+
" current_coords = [lat, long]\n",
7393
" current_ts = datetime.strptime(current_ts, date_format)\n",
7494
" \n",
7595
" try:\n",
76-
" number_to_drop = find(time_window, lambda ts: current_ts - ts < time_threshold)\n",
96+
" number_to_drop = find(time_window, lambda ts: current_ts - ts <= time_threshold)\n",
7797
" left_index += number_to_drop\n",
7898
" dropn(time_window, number_to_drop)\n",
7999
" dropn(space_window, number_to_drop)\n",
@@ -82,12 +102,10 @@
82102
" time_window.clear()\n",
83103
" space_window.clear()\n",
84104
" \n",
85-
" current_coords = [lat, long]\n",
86-
" \n",
87105
" if len(space_window) > 0:\n",
88106
" distances = dist.pairwise(space_window, [current_coords])\n",
89107
" for i, d in enumerate(np.nditer(distances)):\n",
90-
" if d < space_threshold:\n",
108+
" if d <= space_threshold:\n",
91109
" wr.writerow({\n",
92110
" \"x\": left_index + i,\n",
93111
" \"y\": right_index,\n",
@@ -120,7 +138,7 @@
120138
"source": [
121139
"# Set the input and output locations\n",
122140
"\n",
123-
"working_directory = \"/Users/joshtok/Code/geo-clustering\"\n",
141+
"working_directory = \"/path/to/data\"\n",
124142
"infile = os.path.join(working_directory, \"summer-travel-gps-full.csv\")\n",
125143
"outfile = os.path.join(working_directory, \"sparse_distance_matrix.csv\")\n",
126144
"\n",

0 commit comments

Comments
 (0)