0

I am currently tracking animals in national parks and have lat/long and date/time data for individuals and a polygon shapefile for the park boundary. I want to know how many times individuals leave the park boundary each month and at what time of day. In nearly every instance, the individuals return to the park, so I need to account for directionality or count every other intersection.

At the moment, I am converting the raw data into telemetry paths as an ltraj object with the 'adehabitatlt' package. However, I cannot seem to trim the ltraj objects to the polygon, nor does it retain the associated time data for individual segments.

In the below example, I would want to know how many times and when the ibex leave the sps polygon:

library(adehabitatLT)
library(sp)

data(ibex)

##Sample Polygon
x_coord <- c(895000,  898000,  898000, 895000, 895000)
y_coord <- c(2031000, 2031000, 2033000, 2033000, 2031000)
xy <- cbind(x_coord, y_coord)
p = Polygon(xy)
ps = Polygons(list(p),1)
sps = SpatialPolygons(list(ps))
1
  • Are you assuming the ibex travel in straight lines between point locations? So that if, for example, you have two locations outside but the line between them clips a corner the ibex has gone in and then gone out between those locations?
    – Spacedman
    Commented Dec 30, 2022 at 17:05

1 Answer 1

0

You should not use sp because most of the packages that support it are being retired from the end of 2023, and everyone is being advised to move to sf.

Here's a code to detect when ibex is leaving a polygon :

First, I convert ibex dataset to spatial point. I assume that projection is NTF (Paris) / Lambert zone II (EPSG:27572) because it work with this one but you should provide your projection if you want better answering.

library(adehabitatLT) # get ibex data
library(sf) # spatial vector
library(dplyr) # data manipulation
library(tmap) # plotting result

data(ibex)

# Convert data to spatial point
ibex1 <- ibex[[1]] |> 
   filter(!is.na(x) | !is.na(y)) |> 
   st_as_sf(coords = c("x", "y"), crs = 27572) |> 
   arrange(date)

# Create polygon
xy_coords <- data.frame(x = c(895000,  898000,  898000, 895000, 895000),
                        y = c(2031000, 2031000, 2033000, 2033000, 2031000))

poly <- st_as_sf(xy_coords, coords = c("x", "y"), crs = 27572) |> 
   summarise() |> 
   st_cast("POLYGON") |> 
   st_convex_hull()

# find points inside poly
ibex1 <- ibex1 |> 
   mutate(is_inside = st_intersects(geometry, poly, sparse = FALSE)[,1])

When an ibex is leaving, the next point is not inside poly. I use lead function to shift up column is_inside.

is_inside lead(is_inside) is_leaving
FALSE TRUE FALSE
TRUE TRUE FALSE
TRUE FALSE TRUE
FALSE NA FALSE
# detect leaving
ibex1 <- ibex1 |> 
   mutate(leave_poly = ifelse(is_inside & !lead(is_inside), "leave", NA))

You now have a column that detects the last points before leaving the polygon, in this case the sixth point on 2003-06-02 at 04:00:00.

You can check the result below by converting point to path.

# check result
path <- ibex1 |> 
   arrange(date) |>
   summarise(do_union = FALSE) |>
   st_cast("LINESTRING")

tm_shape(path)+
   tm_lines()+
tm_shape(poly)+
   tm_borders(col = "red")
1
  • Very clever use of lead! This is perfect for what I was looking for, thanks!
    – Taggerung
    Commented Jan 3, 2023 at 4:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.