[This article was first published on r.iresmi.net, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Day 3 of 30DayMapChallenge: « Polygons » (previously). Using data from a previous post on lynx occurrences.

So we mapped the sightings of lynx, but there are a lot of outliers; how can we map the core habitat of the species?

We will use DBSCAN to cluster the points, then we will build a concave hull of these clusters. We arbitrary chose a minimal distance of 12 km between clusters and at least 5 points per clusters. Many coordinates are duplicated so we’ll get rid of artificial one-dimension polygons.

```library(rgbif)
library(tidyverse)
library(sf)
library(leaflet)
library(dbscan)
library(concaveman)

# use existing data from GBIF
# keep valid and recent sightings in France.
lynx <- occ_download_get("0034730-231002084531237") |>
occ_download_import() |>
drop_na(decimalLongitude, decimalLatitude) |>
filter(year >= "2015",
countryCode == "FR",
occurrenceStatus == "PRESENT") |>
st_as_sf(coords = c("decimalLongitude", "decimalLatitude"),
crs = "EPSG:4326",
remove = FALSE)

# Create clusters
# we reproject to a Lambert projection to have units in meters
clusters <- lynx |>
st_transform("EPSG:2154") |>
st_coordinates() |>
dbscan(eps = 12000, minPts = 5)

# Create concave hulls
# we can chose an appropriate concavity parameter
concave_hulls <- lynx |>
bind_cols(tibble(cluster = clusters\$cluster)) |>
filter(cluster != 0) |>
group_by(cluster) |>
summarise(nd = n_distinct(decimalLongitude, decimalLatitude),
.groups = "drop") |>
filter(nd > 2) |>
mutate(geom = map(geometry, ~ concaveman(st_sf(st_sfc(.x)),
concavity = 1.7))) |>
st_drop_geometry() |>
unnest(geom) |>
st_sf(crs = "EPSG:4326") |>
st_zm()```
```lynx |>
leaflet() |>
addCircleMarkers(radius = 0.1, opacity = 0.1) |>
addPolygons(data = concave_hulls, color = "red") |>
addTiles()```

We get 4 clusters: Jura, Vosges (North and South) and West of Dijon. We could estimate a rough lynx occupancy area in France:

```concave_hulls |>
st_area() |>
sum() |>
units::set_units(km^2)```
`17925.6 [km^2]`
To leave a comment for the author, please follow the link and comment on their blog: r.iresmi.net.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

# Never miss an update! Subscribe to R-bloggers to receive e-mails with the latest R posts.(You will not see this message again.)

Click here to close (This popup will not appear again)