Managing Animal Movement Data with 'PostGIS' and R

Integrates R and the 'PostgreSQL/PostGIS' database system to build and manage animal trajectory (movement) data sets. The package relies on 'ltraj' objects from the R package 'adehabitatLT', building the analogous 'pgtraj' data structure in 'PostGIS'. Functions allow users to seamlessly transfer between 'ltraj' and 'pgtraj', as well as build new 'pgtraj' directly from location data stored in the database.

CRAN_Status_Badge Project Status: Active - The project has reached a stable, usable state and is being actively developed. Build Status Appveyor Build status codecov

This is the development area for the package rpostgisLT, a companion package to rpostgis and adehabitatLT, which provides functions to store ltraj (the trajectory data object from adehabitatLT) in a PostGIS-enabled PostgreSQL database.

The package was originally developed during Google Summer of Code 2016, 2017 by Balázs Dukai, with mentors Clément Calenge, David Bucklin, and Mathieu Basille.

You can install the latest released version from CRAN:


You can use update.packages() to update to the latest CRAN version.

Installation of the development version

A stable development version of the package will be available on the project's Github page, which may be ahead the CRAN version. To install it, use the devtools package from Hadley Wickham:


For the latest (possibly unstable) development version, use:


Getting started

Of course, it is necessary to have PostgreSQL with PostGIS extension (ideally, versions 9.5+ and 2.2+, respectively; not tested on older versions). An installer for Windows, Linux and Mac systems can be found at EnterpriseDB. During the install process, make sure to also install the PostGIS extension.

Once you are up and running with PostgreSQL, make sure to enable the PostGIS extension on each database, using:


You're now ready to use rpostgisLT. As a first test, you can try sending a sample ltraj dataset from the adehabitatLT package to the database. First, initiate the connection to the database:

con <- dbConnect("PostgreSQL", dbname = <dbname>, host = <host>, user = <user>, password = <password>)

rpostgisLT stores ltraj in a data format called pgtraj (i.e., the PostGIS version of a trajectory). To store data, rpostgisLT builds the pgtraj data model in a dedicated schema in a database. All rpostgisLT functions specify the name of this schema to be traj by default, but it can be assigned any name you like (and you can have as many pgtraj schemas in a database as you would like). The functions that create pgtraj in rpostgisLT all will create this schema if it doesn't exist prior to building the pgtraj, but you can also create it ahead of time using the function pgtrajSchema.


Since we don't specify the schema name, it defaults to "traj". The data model is now built in that schema. To learn more about the pgtraj data model, view the rpostgisLT: Database model vignette.

We can now load a test dataset, and send it to the database using ltraj2pgtraj:

## Create an object of class "ltraj"
cap <- as.ltraj(xy = capreochiz[,c("x","y")], date = capreochiz$date,
            id = "Roe.Deer", typeII = TRUE,
            infolocs = capreochiz[,4:8])
# send to database
ltraj2pgtraj(con, cap, pgtraj = "test_data")

pgtraj stored in the database can be re-imported as ltraj using the pgtraj2ltraj function:

cap.db <- pgtraj2ltraj(con, "test_data")

rpostgisLT also can create pgtraj from data already stored in a database. Consider the following table storing animal relocations:

-- this is SQL!!
CREATE TABLE gps_data.relocations
  gid serial PRIMARY KEY,                       -- primary key (unique integer value)
  animal_id character varying,                  -- unique animal name or ID
  acquisition_time timestamp with time zone,    -- timestamp of the relocations 
  x double precision,                           -- x coordinate
  y double precision,                           -- y coordinate
  geom geometry(Point,26917),                   -- POINT geometry object created from x and y with SRID = 26917
  error_est int,                                -- estimated error for the relocation
  land_cover int                                -- land cover code for the relocation

To create one pgtraj named "test" from all the data in this table, you could use the asPgtraj function with the following arguments:

          relocations_table = c("gps_data","relocations"),
          pgtrajs = "test",
          animals = "animal_id",
          relocations = "geom",
          timestamps = "acquisition_time",
          rids = "gid",
          note = "pgtraj containing all data from gps_data.relocations.")

Alternatively, you could create one pgtraj for each distinct animal_id in the table, by specifying the pgtraj argument as a column name, e.g.:

          relocations_table = c("gps_data","relocations"),
          pgtrajs = "animal_id",
          animals = "animal_id",
          relocations = "geom",
          timestamps = "acquisition_time",
          rids = "gid"

You can also provide a column storing burst names, to further subdivide single animal's trajectories. Also, if you wish to only create pgtraj from a subset of the table, you can specify additional SQL using the clauses argument, as in this example, where only data from the year 2013 is selected:

          relocations_table = c("gps_data","relocations"),
          pgtrajs = "test_2013",
          animals = "animal_id",
          relocations = "geom",
          timestamps = "acquisition_time",
          rids = "gid",
          clauses = "WHERE extract(year FROM acquisition_time) = 2013"

Finally, you can also attach information on locations (infolocs in an ltraj) using the info_cols argument. By default, the function assumes that these columns are also in relocations_table, but you can specify an alternate table (info_table) and its ID column (info_rids) that matches (JOINs) with the rids column in relocations_table.

          relocations_table = c("gps_data","relocations"),
          pgtrajs = "test_winfolocs",
          animals = "animal_id",
          relocations = "geom",
          timestamps = "acquisition_time",
          rids = "gid",
          info_cols = c("error_est","land_cover")

All pgtraj can be directly imported into R ltraj using pgtraj2ltraj:

test_2013<-pgtraj2ltraj(con, pgtraj = "test_2013")

To see more demonstrations on how ltraj can be modified, written to pgtraj, and re-imported into R without any data alteration, refer to the Use Cases vignette.

Explore a pgtraj

Use the explorePgtraj function to start the Shiny app that allows you to interactively explore a pgtraj. Note that in order to explore a pgtraj, all pgtrajes need to have and SRID assinged to them in the same traj schema.

layer_vector <-
    list(c("example_data", "county_subdiv"),
         c("example_data", "test_points"))
layer_param_vector <-
        test_points = list(
            color = "red",
            stroke = FALSE,
            fillOpacity = 0.5
        county_subdiv = list(
            color = "grey",
            fillOpacity = 0.2
              schema = "traj_schema",
              pgtraj = "pgtraj_name",

By default, explorePgtraj includes OpenStreetMap as a base layer. However, you can also add your own base layers (layer_vector and layer_raster). If you are adding a vector layer, it need to be stored in a database, thus you provide the c(schema_name, table_name) of this layer. If you are adding a raster layer it has to be raster::RasterLayer object.

ras <- rgdal::readGDAL("./temp_data/florida_dem_county099.tif")
ras2 <- raster::raster(ras, 1)
ras2_leaflet <- leaflet::projectRasterForLeaflet(ras2)
              schema = "traj_schema",
              pgtraj = "pgtraj_name",
              layer_raster = ras2_leaflet)

Both vector and raster layers accept a layer_param_* argument where you control how these layers are displayed by Leaflet. The parameter layer_param_vector accepts a named list of lists. Where names need to map to the table names in layer_vector. Sub-lists contain parameters passed to leaflet::addCircleMarkers/addPolylines/addPolygons(). The parameter layer_param_raster accepts a list of parameters passed to leaflet::addRasterImage().

The explorePgtraj shiny app



All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.


0.6.0 - 2017-08-29

Final outcome of GSoC 2017.


  • NEWS formatted according to Keep a Changelog
  • tests are now based on testthat
  • as_pgtraj() -> asPgtraj() for consistent function names


  • explorePgtraj function and shiny app
  • createShinyViews function that create two materialized views, all_burst_summary_shiny and step_geometry_shiny_<pgtraj>
  • supporting functions for the two above in utils_shiny.R
  • continuous integration services (Travis CI and AppVeyor)
  • code coverage reporting

0.5.0 - 2017-06-20


  • example data sets added (Roe deer GPS tracking data set)


  • as_pgtraj: new argument tzone allows for time zone specification, and applies the database time zone if left NULL (formerly used the R (system) time zone)


  • as_pgtraj: fixed bug potentially affecting sorting of steps within a burst in step_geometry view, and subsequently in imported ltraj using pgtraj2ltraj.
  • pgtraj2ltraj: infolocs columns of type POSIXlt now re-import time zone attribute correctly
  • ltraj2pgtraj: fixed bug affecting infolocs factors with commas

0.4 - 2016-11-01



  • Added handling of infolocs
  • Added support for Type I (no time recorded) trajectories
  • New pgtraj and burst summary views
  • faster conversion to pgtraj from database data in as_pgtraj()

0.3 - 2016-08-23


  • Add pgTrajVacuum(), pgTrajDrop()
  • Add ltraj2pgtraj(overwrite = TRUE/FALSE)
  • Add dl_opt(rnames=TRUE/FALSE)
  • The traj database model has changed by adding r_rowname, r2n, rel_angle to the table 'step'.
  • Remove pgTrajR2TempT().
  • Renaming <pgtraj_name>_step_geom –> <pgtraj_name>_step_geometry; <pgtraj_name>_params –> <pgtraj_name>_parameters

0.2.3 - 2016-08-10


  • Depends on adehabitatLT package.
  • Add <pgtraj_name>_step_geom view for visualizing pgtrajes in QGIS.
  • The traj database model has changed, including field and table name changes.
  • Remove pgDropTempT().

0.2.2 - 2016-08-01


  • Bugfix version, no changes visible to the user.

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.


0.6.0 by Balázs Dukai, a year ago

Report a bug at

Browse source code at

Authors: Balázs Dukai [aut, cre] (Package creator during Google Summer of Code 2016 and 2017) , Mathieu Basille [aut] , David Bucklin [aut] , Clément Calenge [ctb]

Documentation:   PDF Manual  

GPL (>= 3) license

Imports sp, lubridate, shiny, leaflet, htmltools, mapview, shinyWidgets, magrittr, sf

Depends on DBI, RPostgreSQL, rpostgis, adehabitatLT

Suggests knitr, raster, rmarkdown, testthat

System requirements: PostgreSQL with PostGIS extension

See at CRAN