SkillAgentSearch skills...

Gpkg

Utilities for the Open Geospatial Consortium (OGC) 'GeoPackage' Format in R

Install / Use

/learn @brownag/Gpkg
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<!-- README.md is generated from README.Rmd. Please edit that file -->

gpkg - Utilities for the Open Geospatial Consortium ‘GeoPackage’ Format

<!-- badges: start -->

R-CMD-check gpkg HTML
Manual CRAN
status Codecov test
coverage

<!-- badges: end -->

High-level wrapper functions to build Open Geospatial Consortium (OGC) ‘GeoPackage’ files. GDAL utilities for read and write of spatial data (vector and gridded) are provided via the {terra} package. Additional ‘GeoPackage’ and ‘SQLite’ specific functions manipulate attributes and tabular data via the {RSQLite} package.

<a href="https://raw.githubusercontent.com/brownag/gpkg/main/man/figures/gpkg_sticker_v1.png"> <img src = "https://raw.githubusercontent.com/brownag/gpkg/main/man/figures/gpkg_sticker_v1.png" alt = "gpkg hexsticker" title = "gpkg hexsticker: {gpkg} provides high-level wrapper functions to build GeoPackages containing a variety of different data." width = "35%" height = "35%" hspace="25" vspace="25" align="right"/></a>

Installation

Install the latest release from CRAN:

install.packages("gpkg")

The development package can be installed from GitHub with {remotes}

if (!requireNamespace("remotes")) 
  install.packages("remotes")
remotes::install_github("brownag/gpkg")

Background

What is a GeoPackage?

GeoPackage is an open, standards-based, platform-independent, portable, self-describing, compact format for transferring geospatial information. The GeoPackage Encoding Standard describes a set of conventions for storing the following within an SQLite database:

  • vector features

  • tile matrix sets of imagery and raster maps at various scales

  • attributes (non-spatial data)

  • extensions

Create a Geopackage

gpkg_write() can handle a variety of different input types. Here we start by adding two DEM (GeoTIFF) files.

library(gpkg)
library(terra)
#> terra 1.8.56

dem <- system.file("extdata", "dem.tif", package = "gpkg")
stopifnot(nchar(dem) > 0)
gpkg_tmp <- tempfile(fileext = ".gpkg")

if (file.exists(gpkg_tmp))
  file.remove(gpkg_tmp)

# write a gpkg with two DEMs in it
gpkg_write(
  dem, gpkg_tmp,
  RASTER_TABLE = "DEM1",
  FIELD_NAME = "Elevation"
)
#> Loading required namespace: gdalraster

gpkg_write(
  dem, gpkg_tmp,
  append = TRUE,
  RASTER_TABLE = "DEM2",
  FIELD_NAME = "Elevation",
  NoData = -9999
)

Insert Vector Layers

We can also write vector data to GeoPackage. Here we use gpkg_write() to add a bounding box polygon layer derived from extent of "DEM1".

# add bounding polygon vector layer via named list
r <- gpkg_tables(gpkg_tmp)[['DEM1']]
v <- terra::as.polygons(r, ext = TRUE)
gpkg_write(list(bbox = v), gpkg_tmp)

Insert Attribute Table

Similarly, data.frame-like objects (non-spatial “attributes”) can be written to GeoPackage.

z <- data.frame(a = 1:10, b = LETTERS[1:10])
gpkg_write(list(myattr = z), gpkg_tmp)

Read a GeoPackage

geopackage() is a constructor that can create a simple container for working with geopackages from several types of inputs. Often you will have a character file path to a GeoPackage (.gpkg) file.

g <- geopackage(gpkg_tmp, connect = TRUE)
g
#> <geopackage>
#> --------------------------------------------------------------------------------
#> # of Tables: 20
#>  
#>  DEM1, DEM2, bbox, gpkg_2d_gridded_coverage_ancillary,
#>  gpkg_2d_gridded_tile_ancillary, gpkg_contents, gpkg_extensions,
#>  gpkg_geometry_columns, gpkg_metadata, gpkg_metadata_reference,
#>  gpkg_ogr_contents, gpkg_spatial_ref_sys, gpkg_tile_matrix,
#>  gpkg_tile_matrix_set, myattr, rtree_bbox_geom, rtree_bbox_geom_node,
#>  rtree_bbox_geom_parent, rtree_bbox_geom_rowid, sqlite_sequence
#> --------------------------------------------------------------------------------
#> <SQLiteConnection>
#>   Path: /tmp/RtmpDk7Fhe/filedd0d473fa3bd.gpkg
#>   Extensions: TRUE
class(g)
#> [1] "geopackage"

Other times you may have a list of tables and layers you want to be in a GeoPackage that does not exist yet.

g2 <- geopackage(list(dem = r, bbox = v))
g2
#> <geopackage>
#> --------------------------------------------------------------------------------
#> # of Tables: 18
#>  
#>  bbox, dem, gpkg_2d_gridded_coverage_ancillary,
#>  gpkg_2d_gridded_tile_ancillary, gpkg_contents, gpkg_extensions,
#>  gpkg_geometry_columns, gpkg_metadata, gpkg_metadata_reference,
#>  gpkg_ogr_contents, gpkg_spatial_ref_sys, gpkg_tile_matrix,
#>  gpkg_tile_matrix_set, rtree_bbox_geom, rtree_bbox_geom_node,
#>  rtree_bbox_geom_parent, rtree_bbox_geom_rowid, sqlite_sequence
#> --------------------------------------------------------------------------------
class(g2)
#> [1] "geopackage"

Note that a temporary GeoPackage ({r, eval=exists(g2)} gpkg_source(g2)) is automatically created when using the geopackage(<list>) constructor.

You also may have a DBIConnection to a GeoPackage database already opened that you want to use. In any case (character, list, SQLiteConnection) there is an S3 method to facilitate creating the basic geopackage class provided by {gpkg}. All other methods are designed to be able to work smoothly with geopackage class input.

Inspect Contents of GeoPackage

We can list the table names in a GeoPackage with gpkg_list_tables() and fetch pointers (SpatRaster, SpatVectorProxy, and lazy data.frame) to the data in them with gpkg_table(). We can check the status of the internal geopackage class SQLiteConnection with gpkg_is_connected() and disconnect it with gpkg_disconnect().

# enumerate tables
gpkg_list_tables(g)
#>  [1] "DEM1"                               "DEM2"                              
#>  [3] "bbox"                               "gpkg_2d_gridded_coverage_ancillary"
#>  [5] "gpkg_2d_gridded_tile_ancillary"     "gpkg_contents"                     
#>  [7] "gpkg_extensions"                    "gpkg_geometry_columns"             
#>  [9] "gpkg_metadata"                      "gpkg_metadata_reference"           
#> [11] "gpkg_ogr_contents"                  "gpkg_spatial_ref_sys"              
#> [13] "gpkg_tile_matrix"                   "gpkg_tile_matrix_set"              
#> [15] "myattr"                             "rtree_bbox_geom"                   
#> [17] "rtree_bbox_geom_node"               "rtree_bbox_geom_parent"            
#> [19] "rtree_bbox_geom_rowid"              "sqlite_sequence"

# inspect tables
gpkg_tables(g)
#> $DEM1
#> class       : SpatRaster 
#> size        : 30, 31, 1  (nrow, ncol, nlyr)
#> resolution  : 0.008333333, 0.008333333  (x, y)
#> extent      : 6.008333, 6.266667, 49.69167, 49.94167  (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#> source      : filedd0d473fa3bd.gpkg:DEM1 
#> varname     : filedd0d473fa3bd 
#> name        : DEM1 
#> min value   :  195 
#> max value   :  500 
#> 
#> $DEM2
#> class       : SpatRaster 
#> size        : 30, 31, 1  (nrow, ncol, nlyr)
#> resolution  : 0.008333333, 0.008333333  (x, y)
#> extent      : 6.008333, 6.266667, 49.69167, 49.94167  (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#> source      : filedd0d473fa3bd.gpkg:DEM2 
#> varname     : filedd0d473fa3bd 
#> name        : DEM2 
#> min value   :  195 
#> max value   :  500 
#> 
#> $myattr
#>                                     dsn table_name nrow table_info.cid
#> 1 /tmp/RtmpDk7Fhe/filedd0d473fa3bd.gpkg     myattr   10              0
#> 2 /tmp/RtmpDk7Fhe/filedd0d473fa3bd.gpkg     myattr   10              1
#>   table_info.name table_info.type table_info.notnull table_info.dflt_value
#> 1               a         INTEGER                  0                    NA
#> 2               b            TEXT                  0                    NA
#>   table_info.pk
#> 1             0
#> 2             0
#> 
#> $bbox
#>  class       : SpatVector 
#>  geometry    : polygons 
#>  dimensions  : 1, 0  (geometries, attributes)
#>  extent      : 6.008333, 6.266667, 49.69167, 49.94167  (xmin, xmax, ymin, ymax)
#>  source      : filedd0d473fa3bd.gpkg (bbox)
#>  coord. ref. : lon/lat WGS 84 (EPSG:4326)

# inspect a specific table
gpkg_table(g, "myattr", collect = TRUE)
#>     a b
#> 1   1 A
#> 2   2 B
#> 3   3 C
#> 4   4 D
#> 5   5 E
#> 6   6 F
#> 7   7 G
#> 8   8 H
#> 9   9 I
#> 10 10 J

Note that the collect = TRUE forces data be loaded into R memory for vector and attribute data; this is the difference in result object class of SpatVectorProxy/SpatVector and tbl_SQLiteConnection/data.frame for vector and attribute data, respectively.

gpkg_collect() is a helper method to call gpkg_table(..., collect = TRUE) for in-memory loading of specific tables.

gpkg_collect(g, "DEM1")
#>   id zoom_level tile_column tile_row     tile_data
#> 1  1          0           0        0 blob[3.98 kB]

Note that with grid data returned from gpkg_collect() you get a table result with the tile contents in a blob column of a data.frame instead of SpatRaster object.

The inverse function of gpkg_collect() is gpkg_tbl() which always returns a tbl_SQLiteConnection.

tb <- gpkg_tbl(g, "gpkg_contents")
tb
#> # Source:   table<`gpkg_contents`> [?? x 10]
#> # Database: sqlite
View on GitHub
GitHub Stars24
CategoryData
Updated1mo ago
Forks0

Languages

R

Security Score

95/100

Audited on Feb 27, 2026

No findings