HLCtools calculates Herd Lying Concordance (HLC) metrics
from individual animal lying-behaviour data.
HLC is a framework for quantifying group-level behavioural cohesion. Instead of classifying an interval as synchronous using a fixed threshold, HLC uses the distribution of individual animal lying behaviour within each interval.
The package currently supports four HLC implementations:
HLC_SD: standard-deviation-based HLCHLC_MAD: mean-absolute-deviation-based HLCHLC_IQR: interquartile-range-based HLCHLC_ENT: entropy-based HLCThe package also calculates lying-weighted HLC, which combines group cohesion with the proportion of the interval spent lying.
library(HLCtools)
data(example_lies)
example_lies
#> group day week time cow lying
#> 1 A 1 1 00:00 cow1 15
#> 2 A 1 1 00:15 cow2 15
#> 3 A 1 1 00:00 cow3 15
#> 4 A 1 1 00:15 cow4 15
#> 5 A 1 1 00:00 cow5 15
#> 6 A 1 1 00:15 cow1 0
#> 7 A 1 1 00:00 cow2 0
#> 8 A 1 1 00:15 cow3 0
#> 9 A 1 1 00:00 cow4 0
#> 10 A 1 1 00:15 cow5 0
#> 11 A 2 1 00:00 cow1 15
#> 12 A 2 1 00:15 cow2 15
#> 13 A 2 1 00:00 cow3 15
#> 14 A 2 1 00:15 cow4 0
#> 15 A 2 1 00:00 cow5 0
#> 16 A 2 1 00:15 cow1 15
#> 17 A 2 1 00:00 cow2 0
#> 18 A 2 1 00:15 cow3 15
#> 19 A 2 1 00:00 cow4 0
#> 20 A 2 1 00:15 cow5 15
#> 21 B 1 1 00:00 cow1 15
#> 22 B 1 1 00:15 cow2 15
#> 23 B 1 1 00:00 cow3 10
#> 24 B 1 1 00:15 cow4 10
#> 25 B 1 1 00:00 cow5 15
#> 26 B 1 1 00:15 cow1 15
#> 27 B 1 1 00:00 cow2 12
#> 28 B 1 1 00:15 cow3 15
#> 29 B 1 1 00:00 cow4 8
#> 30 B 1 1 00:15 cow5 15
#> 31 B 2 1 00:00 cow1 0
#> 32 B 2 1 00:15 cow2 0
#> 33 B 2 1 00:00 cow3 5
#> 34 B 2 1 00:15 cow4 0
#> 35 B 2 1 00:00 cow5 0
#> 36 B 2 1 00:15 cow1 0
#> 37 B 2 1 00:00 cow2 15
#> 38 B 2 1 00:15 cow3 0
#> 39 B 2 1 00:00 cow4 15
#> 40 B 2 1 00:15 cow5 0The input data should contain one row per animal per time interval.
At minimum, the data should contain:
Optional but usually useful columns include:
In example_lies, the relevant columns are:
str(example_lies)
#> 'data.frame': 40 obs. of 6 variables:
#> $ group: chr "A" "A" "A" "A" ...
#> $ day : int 1 1 1 1 1 1 1 1 1 1 ...
#> $ week : num 1 1 1 1 1 1 1 1 1 1 ...
#> $ time : chr "00:00" "00:15" "00:00" "00:15" ...
#> $ cow : chr "cow1" "cow2" "cow3" "cow4" ...
#> $ lying: num 15 15 15 15 15 0 0 0 0 0 ...hlc_intervals <- calculate_hlc(
data = example_lies,
group = group,
animal = cow,
day = day,
period = week,
interval = time,
lying = lying,
interval_min = 15,
methods = c("sd", "mad", "iqr", "entropy"),
sync_thresholds = c(0.6, 0.7, 0.8, 0.9),
add_lying_weighted = TRUE
)
hlc_intervals
#> # A tibble: 8 × 24
#> group day week time n_animals mean_lying lying_prop sd_lying mad_lying
#> <chr> <int> <dbl> <chr> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 A 1 1 00:00 5 9 0.6 7.35 7.2
#> 2 A 1 1 00:15 5 6 0.4 7.35 7.2
#> 3 A 2 1 00:00 5 6 0.4 7.35 7.2
#> 4 A 2 1 00:15 5 12 0.8 6 4.8
#> 5 B 1 1 00:00 5 12 0.8 2.76 2.4
#> 6 B 1 1 00:15 5 14 0.933 2 1.6
#> 7 B 2 1 00:00 5 7 0.467 6.78 6.4
#> 8 B 2 1 00:15 5 0 0 0 0
#> # ℹ 15 more variables: iqr_lying <dbl>, p_lying <dbl>, HLC_SD <dbl>,
#> # HLC_MAD <dbl>, HLC_IQR <dbl>, entropy_raw <dbl>, HLC_ENT <dbl>,
#> # sync60 <int>, sync70 <int>, sync80 <int>, sync90 <int>, HLC_SD_LYING <dbl>,
#> # HLC_MAD_LYING <dbl>, HLC_IQR_LYING <dbl>, HLC_ENT_LYING <dbl>The output contains one row per group-time interval.
Important columns include:
mean_lying: mean lying minutes in the interval;lying_prop: mean lying proportion in the interval;HLC_SD, HLC_MAD, HLC_IQR,
HLC_ENT: unweighted HLC metrics;HLC_SD_LYING, HLC_MAD_LYING,
HLC_IQR_LYING, HLC_ENT_LYING: lying-weighted
HLC metrics;sync60, sync70, sync80,
sync90: threshold synchrony indicators.hlc_daily <- summarise_hlc_daily(
data = hlc_intervals,
group = group,
day = day,
period = week,
interval_min = 15
)
hlc_daily
#> # A tibble: 4 × 19
#> group day week mean_HLC_SD mean_HLC_MAD mean_HLC_IQR mean_HLC_ENT
#> <chr> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 A 1 1 0.0202 0.0400 0 0.0290
#> 2 A 2 1 0.110 0.2 0.5 0.154
#> 3 B 1 1 0.683 0.733 0.833 1
#> 4 B 2 1 0.548 0.573 0.5 0.515
#> # ℹ 12 more variables: mean_HLC_SD_LYING <dbl>, mean_HLC_MAD_LYING <dbl>,
#> # mean_HLC_IQR_LYING <dbl>, mean_HLC_ENT_LYING <dbl>, sync60_time_min <dbl>,
#> # sync70_time_min <dbl>, sync80_time_min <dbl>, sync90_time_min <dbl>,
#> # mean_lying_min_interval <dbl>, mean_lying_prop <dbl>, n_intervals <int>,
#> # mean_n_animals <dbl>The daily summary contains one row per group-day.
Daily HLC columns are means of interval-level HLC values. Synchrony threshold columns are summarised as minutes per day.
Different experiments may favour different HLC implementations. For example, one dataset may favour SD-based HLC, whereas another may favour MAD-, IQR-, or entropy-based HLC.
rank_hlc_methods() provides a descriptive ranking of
available HLC implementations.
rank_hlc_methods(
data = hlc_daily,
group = group,
period = week,
lying_prop = mean_lying_prop
)
#> method metric_column n_total n_non_missing pct_missing mean sd
#> 1 HLC_SD mean_HLC_SD 4 4 0 0.3402575 0.3244934
#> 2 HLC_MAD mean_HLC_MAD 4 4 0 0.3866667 0.3214781
#> 3 HLC_ENT mean_HLC_ENT 4 4 0 0.4242837 0.4355433
#> 4 HLC_IQR mean_HLC_IQR 4 4 0 0.4583333 0.3435921
#> median min max n_unique pct_boundary zero_variance
#> 1 0.3289734 0.02020410 0.6828793 4 0 FALSE
#> 2 0.3866667 0.04000000 0.7333333 4 0 FALSE
#> 3 0.3340427 0.02904941 1.0000000 4 25 FALSE
#> 4 0.5000000 0.00000000 0.8333333 3 25 FALSE
#> high_boundary_collapse degeneracy_score detectability_F detectability_p
#> 1 FALSE 0 46.014560 0.02104854
#> 2 FALSE 0 22.222222 0.04217371
#> 3 FALSE 0 7.062389 0.11721597
#> 4 FALSE 0 1.923077 0.29985996
#> delta_AIC temporal_sd outlier_sensitivity outlier_distance_from_1
#> 1 10.7134285 NaN 0.8296094 0.1703906
#> 2 7.9764932 NaN 0.8131274 0.1868726
#> 3 4.0439423 NaN 1.2102363 0.2102363
#> 4 0.6949164 NaN 1.3904983 0.3904983
#> lying_prop_spearman rank_detectability rank_temporal_stability
#> 1 0.4000000 1 NA
#> 2 0.4000000 2 NA
#> 3 0.4000000 3 NA
#> 4 0.6324555 4 NA
#> rank_outlier_robustness rank_boundary rank_missingness rank_degeneracy
#> 1 1 1.5 2.5 2.5
#> 2 2 1.5 2.5 2.5
#> 3 3 3.5 2.5 2.5
#> 4 4 3.5 2.5 2.5
#> n_ranked_criteria weighted_rank_score selected
#> 1 5 1.7 TRUE
#> 2 5 2.1 FALSE
#> 3 5 2.9 FALSE
#> 4 5 3.3 FALSE
#> recommendation_note
#> 1 Selected/ranked under available criteria.
#> 2 Selected/ranked under available criteria.
#> 3 Selected/ranked under available criteria.
#> 4 Selected/ranked under available criteria.The ranking does not prove that one method is universally best. It provides a transparent dataset-specific summary to support method selection.
Unweighted HLC describes group-level behavioural cohesion.
A high unweighted HLC value means that animals behaved similarly within the interval. This can occur when animals are uniformly lying or uniformly standing.
Lying-weighted HLC describes cohesive lying specifically.
A high lying-weighted HLC value means that animals were both behaviourally cohesive and lying.
The two metrics can be interpreted together:
HLCtools does not assume that one dispersion basis is
universally best.
The choice of SD, MAD, IQR, entropy, or another implementation should depend on:
Researchers are encouraged to calculate multiple HLC variants and report the dispersion basis used.
If you use HLCtools, please cite the package:
citation("HLCtools")
#> To cite package 'HLCtools' in publications use:
#>
#> Amorim Franchi G (2026). _HLCtools: Calculate Herd Lying Concordance
#> Metrics_. R package version 0.1.0. Developed at Aarhus University.,
#> <https://github.com/guilhermefranchi/HLCtools>.
#>
#> A BibTeX entry for LaTeX users is
#>
#> @Manual{,
#> title = {HLCtools: Calculate Herd Lying Concordance Metrics},
#> author = {Guilherme {Amorim Franchi}},
#> year = {2026},
#> note = {R package version 0.1.0. Developed at Aarhus University.},
#> institution = {Aarhus University},
#> url = {https://github.com/guilhermefranchi/HLCtools},
#> }HLCtools was developed at Aarhus University as research
software for calculating Herd Lying Concordance metrics from individual
animal lying-behaviour data.