Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
74314e8
add optional n arg for using asserts within asserts
robitalec Nov 6, 2025
856f399
fst assert_threshold
robitalec Nov 6, 2025
e8438bf
fst assert_units_match
robitalec Nov 6, 2025
1385543
fix return NULL
robitalec Nov 6, 2025
7d771af
param crs
robitalec Nov 6, 2025
6b09d80
inherit returnDist from edge_dist
robitalec Nov 6, 2025
2e0b842
describe crs
robitalec Nov 6, 2025
1c7315d
add crs arg
robitalec Nov 6, 2025
d2e69e2
describe return, link st_distance
robitalec Nov 6, 2025
aaae9bc
inherit from group_pts
robitalec Nov 6, 2025
60f65fd
describe returnDist
robitalec Nov 6, 2025
01d6b62
setup for distance_to_*
robitalec Nov 6, 2025
40b841b
use calc_distance for distance_to_*
robitalec Nov 6, 2025
0b73ffe
if crs is NULL set to NA_crs_
robitalec Nov 6, 2025
d33fafb
use calc_distance
robitalec Nov 6, 2025
5fbbb4a
use assert_threshold, set units of threshold to crs if crs isnt NA_crs_
robitalec Nov 6, 2025
c279090
mv inherit crs to dist
robitalec Nov 3, 2025
58277e0
add crs arg
robitalec Nov 3, 2025
dfa11bc
Merge branch 'main' into feat/use-calc-distance
robitalec Nov 10, 2025
f2d0075
Merge branch 'main' into feat/use-calc-distance
robitalec Dec 2, 2025
103dd2d
use out col
robitalec Dec 2, 2025
79dce55
use env
robitalec Dec 2, 2025
004237e
else coords
robitalec Dec 2, 2025
832ec83
tidy, use env, etc for if rank
robitalec Dec 2, 2025
1aa0ab2
if coords null, use geometry
robitalec Dec 2, 2025
7b0e551
fix NSE
robitalec Dec 2, 2025
aa1db39
use matching name from dir to
robitalec Dec 2, 2025
1a50e17
add geometry arg
robitalec Dec 2, 2025
3835228
fix NSE
robitalec Dec 2, 2025
88c4097
else coords
robitalec Dec 2, 2025
32ca5e3
if null use geometry
robitalec Dec 2, 2025
80a5a9c
out_col
robitalec Dec 2, 2025
8f8fbe3
tidy setup
robitalec Dec 2, 2025
2f4772c
fix if set units on threshold
robitalec Dec 4, 2025
d1b3e66
add geometry arg
robitalec Dec 4, 2025
3706f6b
else coords
robitalec Dec 4, 2025
9abf1c0
add use_dist arg
robitalec Dec 4, 2025
1ea2a9b
pairwise dist
robitalec Dec 4, 2025
0f8ed9c
fix indent
robitalec Dec 4, 2025
9efc122
add use_dist flag
robitalec Dec 4, 2025
48d6876
tidy ugh bad merge
robitalec Dec 4, 2025
22286f5
pairwise, matrix options for use_dist T/F
robitalec Dec 4, 2025
c59ba41
set units on threshold also only if use_dist T
robitalec Dec 4, 2025
81e7006
fix expect dist class when use_dist
robitalec Dec 4, 2025
2d0ef1a
fix expect dims differ when use_dist T
robitalec Dec 4, 2025
f4776d7
breaking: only calculate group if X+Y aren't NA
robitalec Dec 5, 2025
fa19544
fix also use_dist when crs NA
robitalec Dec 5, 2025
0f9d177
add test group NA if X/Y NA
robitalec Dec 5, 2025
a7d7680
fix return as.matrix
robitalec Dec 5, 2025
e42fcb0
fix allow NULL crs set to NA_crs_
robitalec Dec 5, 2025
04ea364
fix use use_dist
robitalec Dec 5, 2025
f3f788f
add proj_geometry
robitalec Dec 5, 2025
bc5e8da
fix expect double matrix
robitalec Dec 5, 2025
46350f9
add tests for use_dist TRUE
robitalec Dec 5, 2025
5c2e44d
fix missing use_dist, if TRUE no units
robitalec Dec 5, 2025
08de027
add na.last = 'keep' to keep NAs NA
robitalec Dec 5, 2025
4d6dd3b
add filter xy na
robitalec Dec 5, 2025
608f5fd
fix, expand nas returned as expected test
robitalec Dec 5, 2025
ec2e1c4
if null use geo
robitalec Dec 5, 2025
7cf543c
add else if threshold not numeric or units stop
robitalec Dec 5, 2025
f82cc1c
fix missing args
robitalec Dec 5, 2025
7cfbb3c
reflow
robitalec Dec 5, 2025
cc3d5da
fix missing asserts
robitalec Dec 5, 2025
bcc66aa
fix '/''
robitalec Dec 5, 2025
483b17b
add warn overwrite for geo
robitalec Dec 5, 2025
1ab754e
fix add use_dist
robitalec Dec 5, 2025
7624cbd
fix use out_col, fix dist not dir
robitalec Dec 5, 2025
cc67537
fix since default geo
robitalec Dec 5, 2025
a71f082
fix missing units::
robitalec Dec 5, 2025
955a12e
fix obj nm
robitalec Dec 5, 2025
8216602
fix also allow threshold NULL
robitalec Dec 5, 2025
7d623c7
add geo arg
robitalec Dec 5, 2025
11b78d4
organize into else coords
robitalec Dec 5, 2025
860214a
if coords null, use geo
robitalec Dec 5, 2025
962baad
fix use dist and env
robitalec Dec 5, 2025
c8ebda8
else if coords provided
robitalec Dec 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 99 additions & 33 deletions R/distance_to_centroid.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
#' `data.table::frank`, see details at
#' [`?data.table::frank()`][data.table::frank].
#'
#' The `crs` argument expects a character string or numeric defining the
#' coordinate reference system to be passed to [sf::st_crs]. For example, for
#' UTM zone 36S (EPSG 32736), the crs argument is `crs = "EPSG:32736"` or
#' `crs = 32736`. See <https://spatialreference.org> for a list of EPSG codes.
#'
#' @param DT input data.table with centroid columns generated by eg.
#' `centroid_group`
#' @param group group column name, generated by `group_pts`, default
Expand All @@ -30,12 +35,19 @@
#' FALSE
#' @param ties.method see [`?data.table::frank()`][data.table::frank]
#' @inheritParams group_pts
#' @inheritParams direction_step
#'
#' @return `distance_to_centroid` returns the input `DT` appended with a
#' `distance_centroid` column indicating the distance to the group centroid
#' and, optionally, a `rank_distance_centroid` column indicating the within
#' group rank distance to the group centroid (if `return_rank = TRUE`). The
#' distance is returned in the units of the crs
#' (`units(st_crs(crs)$SemiMajor)`). A value of 0 is returned when the
#' coordinates of the focal individual equal the coordinates of the centroid.
#'
#' @return `distance_to_centroid` returns the input `DT` appended with
#' a `distance_centroid` column indicating the distance to group centroid
#' and, optionally, a `rank_distance_centroid` column indicating the
#' within group rank distance to group centroid (if `return_rank =
#' TRUE`).
#' The underlying distance function ([sf::st_distance]) uses different
#' distance measures depending on the input `crs` and the option returned by
#' [sf::sf_use_s2]. See more details under `?sf_distance`.
#'
#' A message is returned when `distance_centroid` and optional
#' `rank_distance_centroid` columns already exist in the input `DT`,
Expand All @@ -47,7 +59,7 @@
#' @export
#' @family Distance functions
#' @family Centroid functions
#' @seealso [centroid_group], [group_pts]
#' @seealso [centroid_group], [group_pts], [sf::st_distance()]
#' @references
#' See examples of using distance to group centroid:
#' * \doi{doi:10.1016/j.anbehav.2021.08.004}
Expand Down Expand Up @@ -80,60 +92,114 @@
#' DT,
#' coords = c('X', 'Y'),
#' group = 'group',
#' crs = 32736,
#' return_rank = TRUE
#' )
distance_to_centroid <- function(
DT = NULL,
coords = NULL,
group = 'group',
crs = NULL,
return_rank = FALSE,
ties.method = NULL) {
ties.method = NULL,
geometry = 'geometry') {

# Due to NSE notes in R CMD check
distance_centroid <- rank_distance_centroid <- NULL
geo <- cent <- x <- y <- x_centroid <- y_centroid <- NULL

assert_not_null(DT)
assert_is_data_table(DT)

assert_are_colnames(DT, coords)
assert_length(coords, 2)
assert_col_inherits(DT, coords, 'numeric')

assert_not_null(return_rank)

if ('distance_centroid' %in% colnames(DT)) {
message('distance_centroid column will be overwritten by this function')
data.table::set(DT, j = 'distance_centroid', value = NULL)
}
out <- 'distance_centroid'

if (is.null(coords)) {
if (!is.null(crs)) {
message('crs argument is ignored when coords are null, using geometry')
}

assert_are_colnames(DT, geometry, ', did you run get_geometry()?')
assert_col_inherits(DT, geometry, 'sfc_POINT')
centroid_col <- 'centroid'
assert_are_colnames(DT, centroid_col, ', did you run centroid_group?')
assert_col_inherits(DT, centroid_col, 'sfc_POINT')

if (out %in% colnames(DT)) {
message(out, ' column will be overwritten by this function')
data.table::set(DT, j = out, value = NULL)
}
crs <- sf::st_crs(DT[[geometry]])
use_dist <- isFALSE(sf::st_is_longlat(crs)) || identical(crs, sf::NA_crs_)

DT[, c(out) := calc_distance(
geometry_a = geo,
geometry_b = cent,
use_dist = use_dist
),
env = list(geo = geometry, cent = centroid_col)
]

xcol <- data.table::first(coords)
ycol <- data.table::last(coords)
pre <- 'centroid_'
centroid_xcol <- paste0(pre, xcol)
centroid_ycol <- paste0(pre, ycol)
centroid_coords <- c(centroid_xcol, centroid_ycol)
} else {
if (is.null(crs)) {
crs <- sf::NA_crs_
}

assert_are_colnames(DT, coords)
assert_length(coords, 2)
assert_col_inherits(DT, coords, 'numeric')

xcol <- data.table::first(coords)
ycol <- data.table::last(coords)
pre <- 'centroid_'
xcol_centroid <- paste0(pre, xcol)
ycol_centroid <- paste0(pre, ycol)
coords_centroid <- c(xcol_centroid, ycol_centroid)

assert_are_colnames(DT, coords_centroid, ', did you run centroid_group?')
assert_col_inherits(DT, coords_centroid, 'numeric')

if (out %in% colnames(DT)) {
message(out, ' column will be overwritten by this function')
data.table::set(DT, j = out, value = NULL)
}

assert_are_colnames(DT, centroid_coords, ', did you run centroid_group?')
assert_col_inherits(DT, centroid_coords, 'numeric')
use_dist <- isFALSE(sf::st_is_longlat(crs)) || identical(crs, sf::NA_crs_)

DT[, distance_centroid :=
sqrt((.SD[[xcol]] - .SD[[centroid_xcol]])^2 +
(.SD[[ycol]] - .SD[[centroid_ycol]])^2)]
DT[!(is.na(x) | is.na(y)),
c(out) := calc_distance(
x_a = x,
y_a = y,
x_b = x_centroid,
y_b = y_centroid,
crs = crs,
use_dist = use_dist
),
env = list(
x = xcol, y = ycol,
x_centroid = xcol_centroid, y_centroid = ycol_centroid
)
]

}

if (return_rank) {
assert_not_null(group)
assert_are_colnames(DT, group, ', did you run group_pts?')

if ('rank_distance_centroid' %in% colnames(DT)) {
out_rank <- 'rank_distance_centroid'
if (out_rank %in% colnames(DT)) {
message(
'rank_distance_centroid column will be overwritten by this function'
out_rank, ' column will be overwritten by this function'
)
data.table::set(DT, j = 'rank_distance_centroid', value = NULL)
data.table::set(DT, j = out_rank, value = NULL)
}

DT[, rank_distance_centroid :=
data.table::frank(distance_centroid, ties.method = ties.method),
by = c(group)]
DT[, c(out_rank) :=
data.table::frank(out, ties.method = ties.method, na.last = 'keep'),
by = group,
env = list(out = out, group = group)]
}

return(DT[])
}
Loading
Loading