Under the hood, a track table is a data frame with a few extra bells and
whistles. Therefore, you can manipulate a track table in the same way you would
a base::data.frame
, tibble::tibble
, or data.table::data.table
(depending
on the data frame class you used as a base for your track table). Anything that
you can do with one of these three data frame classes can be done the same way
with a track table.
There are, however, a few additional things that are specific to track tables and we will review them in this vignette.
But first, let's load a track table that is provided with trackdf
:
library(trackdf) data("tracks") print(tracks, max = 10 * ncol(tracks))
This track table contains the GPS coordinates of two goats foraging through the Tsaobis Nature Park in Namibia, sometimes in 2015.
In addition to the usual information that you can ask about a data frame (e.g., the number of rows and columns, the class of each column, etc), you can access additional information about the content of a track table.
First, you can check whether an object is indeed a track table as follows:
is_track(tracks)
You can also check whether the track table contains geographic coordinates or not as follows:
is_geo(tracks)
You can find out the number of different tracks included in the track table as follows:
n_tracks(tracks)
Finally, you can retrieve the dimensionality (2D or 3D) of the track table as follows:
n_dims(tracks)
Accessing and modifying the different parts (rows, columns, elements) of a track table is similar to accessing and modifying the different parts of the underlying data frame. We will, therefore, not discuss this topic further as it is something that you should already be very familar with.
Note, however, that different data frame classes may do thing slightly
differently from each other. Make sure to know what class is used with the track
tables you are working with. For instance, the track table that we loaded for
this tutorial if of class data.frame
, as indicated in the 6th line of the
print out of the track table:
print(tracks, max = 10 * ncol(tracks))
One particularity of track tables over regular data frames is that they can store geographic data explicitly and perform projection operations to change their coordinate reference system if necessary.
In order to access the coordinate reference system (or projection) of a track table containing geographic data, you simply need to execute the following command:
projection(tracks)
This returns an object of class crs
which is a list consisting of an input
object (usually the character string that you have entered in track
under the
proj
parameter), and a wkt
object which is an automatically generated
WKT 2
representation of the coordinate reference system.
You can modify in place the projection of a track table as follows. This will automatically convert the x and y coordinates contained in the track table to the appropriate projection system:
projection(tracks) <- "+proj=somerc +lat_0=46.9524056 +lon_0=7.43958333 +ellps=bessel +x_0=2600000 +y_0=1200000 +towgs84=674.374,15.056,405.346 +units=m +k_0=1 +no_defs" print(tracks, max = 10 * ncol(tracks))
And back to the original projection:
projection(tracks) <- "+proj=longlat" print(tracks, max = 10 * ncol(tracks))
If you prefer not to modify the original object, you can create a new one with
the new projection using theproject
function as follows:
tracks_somerc <- project(tracks, "+proj=somerc +lat_0=46.9524056 +lon_0=7.43958333 +ellps=bessel +x_0=2600000 +y_0=1200000 +towgs84=674.374,15.056,405.346 +units=m +k_0=1 +no_defs") print(tracks_somerc, max = 10 * ncol(tracks))
Combining track tables requires a bit of caution. Indeed, traditional methods to
combine data frames (e.g., base::rbind
, data.table::rbindlist
, or
dplyr::bind_rows
) will successfully bind together multiple track tables but
they will not check whether these track tables are compatible with each other.
For instance, they will not check that the coordinates are using the same
coordinate reference system or that the time stamps are all in the same time
zone.
In order to ensure that different track tables can be combined without creating
problems down the analysis pipeline, trackdf
provides its own method to bind
multiple track tables together: bind_tracks
.
To demonstrate how bind_tracks
works, let's first create 3 track tables, 2
that are compatible with each other, and 1 that is not.
raw1 <- read.csv(system.file("extdata/gps/02.csv", package = "trackdf")) raw2 <- read.csv(system.file("extdata/gps/03.csv", package = "trackdf")) raw3 <- read.csv(system.file("extdata/video/01.csv", package = "trackdf")) track1 <- track(x = raw1$lon, y = raw1$lat, t = paste(raw1$date, raw1$time), id = 1, proj = "+proj=longlat", tz = "Africa/Windhoek") track2 <- track(x = raw2$lon, y = raw2$lat, t = paste(raw2$date, raw2$time), id = 2, proj = "+proj=longlat", tz = "Africa/Windhoek") track3 <- track(x = raw3$x, y = raw3$y, t = raw3$frame, id = raw3$track_fixed, origin = "2019-03-24 12:55:23", period = "0.04S", tz = "America/New_York")
If you try to combine the 3 track tables using bind_tracks
, an error will be
thrown to let you know that they are not compatible with each other:
bounded_tracks <- bind_tracks(track1, track2, track3)
Compare this to what happens with one of the traditional binding methods:
bounded_tracks <- rbind(track1, track2, track3) print(bounded_tracks, max = 10 * ncol(bounded_tracks))
Here, the tracks tables are combined with each other despite having different
coordinate reference systems and time zones. Using bind_tracks
instead ensures
that this cannot happen.
Track tables are compatible with (most) of the functions from the
"tidyverse". For instance, you can use all the
dplyr
verbs to filter, mutate, group, etc., a
track table, in the same way you would do with a tibble::tibble
or a
base::data.frame
. As long as the result of the operation that you are applying
to a track table does not affect its fundamental structure (see vignette
"Building a track table"), the output that you will get will
remain a track table with its specific attributes.
For instance, here is how to filter a track table to keep only the observations between 2 specific time stamps:
library(dplyr) filtered_tracks <- tracks %>% filter(., t >= as.POSIXct("2015-09-10 07:01:00", tz = "Africa/Windhoek"), t <= as.POSIXct("2015-09-10 07:11:00 CAT", tz = "Africa/Windhoek")) print(filtered_tracks, max = 10 * ncol(filtered_tracks))
You can use any plotting method accepting a data frame of any class to represent the data in a track table.
Here is an example using ggplot2
:
library(ggplot2) ggplot(data = tracks) + aes(x = x, y = y, color = id) + geom_path() + coord_map()
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.