compute_pairwise_distances#

movement.kinematics.compute_pairwise_distances(data, dim, pairs, metric='euclidean', **kwargs)[source]#

Compute pairwise distances between individuals or keypoints.

This function computes the distances between pairs of individuals (i.e. interindividual distances) or pairs of keypoints (i.e. interkeypoint distances), as determined by dim. The distances are computed for the given pairs using the specified metric.

Parameters:
  • data (xarray.DataArray) – The input data containing position information, with time, space (in Cartesian coordinates), and individuals or keypoints (as specified by dim) as required dimensions.

  • dim (Literal["individuals", "keypoints"]) – The dimension to compute the distances for. Must be either 'individuals' or 'keypoints'.

  • pairs (dict[str, str | list[str]] or 'all') –

    Specifies the pairs of elements (either individuals or keypoints) for which to compute distances, depending on the value of dim.

    • If dim='individuals', pairs should be a dictionary where each key is an individual name, and each value is also an individual name or a list of such names to compute distances with.

    • If dim='keypoints', pairs should be a dictionary where each key is a keypoint name, and each value is also keypoint name or a list of such names to compute distances with.

    • Alternatively, use the special keyword 'all' to compute distances for all possible pairs of individuals or keypoints (depending on dim).

  • metric (str, optional) – The distance metric to use. Must be one of the options supported by scipy.spatial.distance.cdist(), e.g. 'cityblock', 'euclidean', etc. Defaults to 'euclidean'.

  • **kwargs (dict) – Additional keyword arguments to pass to scipy.spatial.distance.cdist().

Returns:

The computed pairwise distances. If a single pair is specified in pairs, returns an xarray.DataArray. If multiple pairs are specified, returns a dictionary where each key is a string representing the pair (e.g., 'dist_ind1_ind2' or 'dist_key1_key2') and each value is an xarray.DataArray containing the computed distances for that pair.

Return type:

xarray.DataArray or dict[str, xarray.DataArray]

Raises:

ValueError – If dim is not one of 'individuals' or 'keypoints'; if pairs is not a dictionary or 'all'; or if there are no pairs in data to compute distances for.

Examples

Compute the Euclidean distance (default) between ind1 and ind2 (i.e. interindividual distance), for all possible pairs of keypoints.

>>> position = xr.DataArray(
...     np.arange(36).reshape(2, 3, 3, 2),
...     coords={
...         "time": np.arange(2),
...         "individuals": ["ind1", "ind2", "ind3"],
...         "keypoints": ["key1", "key2", "key3"],
...         "space": ["x", "y"],
...     },
...     dims=["time", "individuals", "keypoints", "space"],
... )
>>> dist_ind1_ind2 = compute_pairwise_distances(
...     position, "individuals", {"ind1": "ind2"}
... )
>>> dist_ind1_ind2
<xarray.DataArray (time: 2, ind1: 3, ind2: 3)> Size: 144B
8.485 11.31 14.14 5.657 8.485 11.31 ... 5.657 8.485 11.31 2.828 5.657 8.485
Coordinates:
* time     (time) int64 16B 0 1
* ind1     (ind1) <U4 48B 'key1' 'key2' 'key3'
* ind2     (ind2) <U4 48B 'key1' 'key2' 'key3'

The resulting dist_ind1_ind2 is a DataArray containing the computed distances between ind1 and ind2 for all keypoints at each time point.

To obtain the distances between key1 of ind1 and key2 of ind2:

>>> dist_ind1_ind2.sel(ind1="key1", ind2="key2")

Compute the Euclidean distance (default) between key1 and key2 (i.e. interkeypoint distance), for all possible pairs of individuals.

>>> dist_key1_key2 = compute_pairwise_distances(
...     position, "keypoints", {"key1": "key2"}
... )
>>> dist_key1_key2
<xarray.DataArray (time: 2, key1: 3, key2: 3)> Size: 144B
2.828 11.31 19.8 5.657 2.828 11.31 14.14 ... 2.828 11.31 14.14 5.657 2.828
Coordinates:
* time     (time) int64 16B 0 1
* key1     (key1) <U4 48B 'ind1' 'ind2' 'ind3'
* key2     (key2) <U4 48B 'ind1' 'ind2' 'ind3'

The resulting dist_key1_key2 is a DataArray containing the computed distances between key1 and key2 for all individuals at each time point.

To obtain the distances between key1 and key2 within ind1:

>>> dist_key1_key2.sel(key1="ind1", key2="ind1")

To obtain the distances between key1 of ind1 and key2 of ind2:

>>> dist_key1_key2.sel(key1="ind1", key2="ind2")

Compute the city block or Manhattan distance for multiple pairs of keypoints using position:

>>> key_dists = compute_pairwise_distances(
...     position,
...     "keypoints",
...     {"key1": "key2", "key3": ["key1", "key2"]},
...     metric="cityblock",
... )
>>> key_dists.keys()
dict_keys(['dist_key1_key2', 'dist_key3_key1', 'dist_key3_key2'])

As multiple pairs of keypoints are specified, the resulting key_dists is a dictionary containing the DataArrays of computed distances for each pair of keypoints.

Compute the city block or Manhattan distance for all possible pairs of individuals using position:

>>> ind_dists = compute_pairwise_distances(
...     position,
...     "individuals",
...     "all",
...     metric="cityblock",
... )
>>> ind_dists.keys()
dict_keys(['dist_ind1_ind2', 'dist_ind1_ind3', 'dist_ind2_ind3'])

See also

scipy.spatial.distance.cdist

The underlying function used.