Offensive Politics » R, and kindly contributed to Want to share your content on R-bloggers? [This article was first published on, and kindly contributed to R-bloggers ]. (You can report issue about the content on this page here Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

According to security researchers the iPhone 4 is logging location data in the background, and apparently sending some part of that data to Apple every day or few days (Wired). Silently recording location data is bad enough, but the data itself is easily recoverable from an iPhone backup. Some enterprising guys (@aallen,@petewarden) wrote an OSX application iPhone Tracker to parse and visualize the location data on a map. As appalled as I was that this data exists, I was also really interested in rewriting their visualization code in R.

Researcher Drew Conway beat me to it with stalkR, but my code is sufficiently different that I think people can learn from both. I’ll walk through the code, links to the github repo are at the end of the post.

Since the location database is stored inside an iOS backup, we’ll need to understand the structure of that backup. The backup contains a bunch of files named with a long hex string, and a few files that provide a binary table of contents. There is some nice python code (iPhone Backup Decoder to open up the table of contents and locate specific files. I was going to translate this code to R, but I decided on a brute-force approach instead. The file we’re looking for is a SQLite database, and contains several unique tables. I just try to open every file in a given backup directory as a SQLite database, and look for a known table name (CellLocation). If the file isn’t a database or the table doesn’t exist then we move on.

library(RSQLite) library(RgoogleMaps) findLocationDB 0) { # we've found it. save this filename filename

Now that we’ve got a function to find a location database, we can access the database and load it into a data frame.

fetchLatLongTimestamp

This fetchLatLongTimestamp function will load the entire location database into a data frame, and then clean up the timestamps and remove bad location data. I had originally seen the time stamp correction code on Prof Jackman’s blog, so thanks to him for that (and pscl!).

Now we’ve got a data frame of Latitude, Longitude, and datetime stamp that looks more or less like this:

Lat Lon Timestamp 38.90612 -77.03961 2011-03-17 17:03:09 38.90563 -77.03929 2011-03-17 17:03:09 38.90567 -77.03957 2011-03-17 17:03:09 38.90574 -77.03988 2011-03-17 17:03:09 38.90561 -77.03967 2011-03-17 17:03:09

The Lat/Lon represents downtown DC, near where I bought my iPhone last month.

Now that we’ve got a data frame full of juicy location data, we need to plot it on a map. I used the fantastic RgoogleMaps package, and ripped most of the vignette (pdf: RgoogleMaps: An R Package for plotting on Google map tiles within R) for loading a map and plotting points by latitude and longitude.

If I’ve got my location data in a data frame called ldata, I can use the following to find the correct bounds and zoom level, fetch a map, and plot my location data. Again, the drawing code is basically ripped from the RgoogleMaps vignette.

## plot a map of all the positions bb

Which gives us:



Obviously I spent a lot of time in Washington, DC, New York, Boston, and Las Vegas. We’re just using R, I can easily slice and dice the data. Let’s say I just wanted to see my Las Vegas data (April 1st – April 4th):

ldata.lv = as.POSIXlt('2011-04-01 23:00:00') & ldata$datetime <= as.POSIXlt('2011-04-04 14:00:00')),] bb.lv

Which gives us:



Yes, I spent a lot of time at the Wynn, Caesar palace, and In n Out Burger.

Here is the full driver code:

## change this to the full path of a backup of an ios 4 device backupPath = as.POSIXlt('2011-04-01 23:00:00') & ldata$datetime <= as.POSIXlt('2011-04-04 14:00:00')),] bb.lv

You can see this code on my iPhone location with R github repo. One big missing feature from the original application is animation, which I may add later. Patches and comments are greatly appreciated!