# Save original state old_opts <- options() old_par <- par(no.readonly = TRUE) old_wd <- getwd() orig_search <- search() # On exit, restore state and detach any new packages on.exit({ options(old_opts) par(old_par) setwd(old_wd) new_pkgs <- setdiff(search(), orig_search) for (pkg in new_pkgs) { if (grepl("^package:", pkg)) { detach(pkg, character.only = TRUE, unload = TRUE) } } }, add = TRUE)
This demo provides context and use cases for the three core functions of the tangles
R package:
tangles
– Anonymises spatial point patterns and raster objects.tangler
– re-applies a known Anonymisation to other data using a detangler object.detangles
– restores Anonymised data back to original coordinates using a valid detangler.The main driver behind this package is confidentiality. While modern science is becoming increasingly open and collaborative, some spatial data—especially that which relates to sensitive locations—must be shared carefully. Anonymisation allows us to retain spatial structure and support robust analysis while obscuring real-world locations.
tangles
Anonymises data through randomized spatial transformations:
Each transformation is stored with a hash-verified detangler, enabling reversible workflows and consistent Anonymisation across related datasets.
tangles
accepts spatial data in the form of:
sf
POINT objectsterra
raster layers or stacksIt also allows exporting of Anonymised point data to shapefiles if needed.
# Load required libraries library(tangles) library(digest) library(terra) library(sf) # Load point data data("HV_subsoilpH") # Load raster data from files ext_path <- system.file("extdata", package = "tangles") rast.files <- list.files(path = ext_path, full.names = TRUE) rasters <- terra::rast(rast.files)
tangles()
can be used directly on sf
objects too. Here's an example with shapefile export:
xyData <- as.matrix(HV_subsoilpH[, 1:2]) tangles.out <- tangles( data = xyData, depth = 3, rasterdata = FALSE, raster_object = FALSE, saveTangles = TRUE, exportShapefile = TRUE, path = tempdir() ) # Using sf input df <- HV_subsoilpH[, 1:2] sf_pts <- st_as_sf(df, coords = c("X", "Y")) tangles.sf.out <- tangles( data = sf_pts, depth = 3, saveTangles = TRUE, exportShapefile = TRUE, path = tempdir() )
You can also use tangles()
directly on raster stacks to Anonymise them, particularly when you want to generate a new detangler object.
tangles.ras.out <- tangles( data = rasters, depth = 3, rasterdata = TRUE, raster_object = TRUE, saveTangles = TRUE, path = tempdir() )
When tangling both point and raster data using the same transformation, it is important to constrain the rotation angles to preserve raster alignment. This can be done by setting rasterdata = TRUE
in the tangles()
call for point data. This ensures that any rotation is limited to 90°, 180°, or 270°, which maintains compatibility with grid-based raster structures.
# 1. Tangling the point data xyData <- as.matrix(HV_subsoilpH[, 1:2]) tangles.out <- tangles( data = xyData, depth = 4, rasterdata = TRUE, raster_object = FALSE, saveTangles = FALSE ) # 2. Tangling the raster data using the same detangler tangler.out <- tangler( data = rasters, tanglerInfo = tangles.out[[2]], raster_object = TRUE, stub = "combined", saveTangles = FALSE ) # 3. Convert points to sf objects original_pts <- st_as_sf(HV_subsoilpH, coords = c("X", "Y")) tangled_pts <- st_as_sf(as.data.frame(tangles.out[[1]]), coords = c("X", "Y")) # 4. Plot both par(mfrow = c(1, 2)) plot(rasters[[1]], main = "Original Raster + Points") plot(original_pts, add = TRUE, pch = 16, col = "blue") plot(tangler.out[[1]][[1]], main = "Tangled Raster + Points") plot(tangled_pts, add = TRUE, pch = 16, col = "red") par(mfrow = c(1, 1))
To restore Anonymised data to its original spatial configuration, use the detangles()
function with the correct tanglerInfo
and hash_key
. This will reverse all transformations in the correct order.
Note:
- For successful restoration, the hash_key
must match the one embedded in the detangler object.
- If working with raster data, ensure the same constraints (e.g., right-angle rotations) were applied during tangling.
- You can optionally export the restored point data as shapefiles using exportShapefile = TRUE
, which is useful for downstream spatial analysis or visualization.
# Detangle points detangled_points <- detangles( data = tangles.out[[1]], tanglerInfo = tangles.out[[2]], raster_object = FALSE, stub = "demo_points", hash_key = tangles.out[[2]]$hash, saveTangles = TRUE, path = tempdir() ) # Detangle rasters detangled_rasters <- detangles( data = tangler.out[[1]], tanglerInfo = tangles.out[[2]], raster_object = TRUE, stub = "demo_raster", hash_key = tangles.out[[2]]$hash, saveTangles = TRUE, path = tempdir() )
The tangles
package provides a reversible and flexible method for Anonymising spatial data. It supports point and raster formats, and can be integrated into privacy-preserving data sharing workflows. While the Anonymised coordinates are spatially transformed, internal spatial relationships (e.g., autocorrelation) remain intact, allowing robust analysis without revealing exact locations.
For best results: - Use non-right-angle rotations only on point data. - For rasters, limit rotations to 90°, 180°, or 270°. - Consider exporting Anonymised points as shapefiles when sharing with collaborators.
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.