Makes column the index, the when$index slot, and re-sorts the frame.
A column that was a when key stops being one. unit declares the unit
of the new index in the same call; without it, the frame goes on
declaring the unit of the old index.
The new index must be numeric, with no missing values, and must increase
within each group of keys (identity plus temporal context) in the order
of the old index, so the rows keep their order: values that go backwards
have been matched to the wrong rows. Date-times are refused: the index
holds the time since the start, as numbers, and the start goes in
start_datetime, so absolute time is start_datetime plus the index.
Arguments
- data
An anipoint object.
- column
Length-one character vector naming the index column. It must exist in
dataand be numeric.- unit
The unit of the new index, one of the levels of
unit_timeinlist_default_metadata().NULL, the default, leavesunit_timeas it is.
The old index
The previous index becomes an ordinary, undeclared column rather than a key, as grouping by it would put each row in a group of its own.
When it counted frames (unit_time is "frame"), it is renamed
frame. Frame numbers recorded with the data are data, not something to
compute again from a rate, and convert_unit_time() makes the frame
column the index again when converting to "frame". An old index
already named frame keeps its name, and so does one replaced by a new
index named frame. If the frame has another column named frame,
set_index() refuses rather than overwrite either; rename one first.
Indexing by recorded timestamps
Timestamps recorded alongside the data, such as a camera's log of when each frame was taken, are added as a column and made the index with their unit:
Here the log has one entry per frame and frames count from 0, so the timestamp of a row is matched by its frame number. Matching by position, assigning the log in row order, lines up only when every group is complete and sorted: an anipoint has one row per time per key, and a keypoint can be missing from some frames. Bringing a log, or any other data, into a frame is a join question, tracked in anicore#1.
The frame numbers move to a column named frame, and a declared
sampling_rate is kept as the nominal rate. sampling_interval is
measured from the timestamps, and validate_anipoint() allows the two to
differ by 1%. Overwriting time with dplyr::mutate() instead would
lose the frame numbers and leave the frame saying the index counts frames
when it holds seconds.
See also
get_index(), convert_unit_time() to rescale the index into
another unit.
Examples
df <- data.frame(frame = 1:3, individual = "a", x = c(1, 2, 3), y = c(0, 1, 0))
af <- as_anipoint(df, index = "frame")
get_index(af)
#> [1] "frame"
# A camera log, one timestamp per frame, frames counted from 0
af <- as_anipoint(data.frame(
individual = "a",
keypoint = rep(c("head", "tail"), each = 4),
time = rep(0:3, 2),
x = 1:8,
y = 1:8
))
stamps <- c(0, 0.0332, 0.0668, 0.1001)
logged <- af |>
dplyr::mutate(timestamp = stamps[time + 1]) |>
set_index("timestamp", unit = "s")
logged
#> # Individuals: a
#> # Keypoints: head, tail
#> # Time: 00:00:00.000 to 00:00:00.100
#> individual keypoint timestamp x y frame
#> <fct> <fct> <dbl> <dbl> <dbl> <int>
#> 1 a head 0 1 1 0
#> 2 a head 0.0332 2 2 1
#> 3 a head 0.0668 3 3 2
#> 4 a head 0.100 4 4 3
#> 5 a tail 0 5 5 0
#> 6 a tail 0.0332 6 6 1
#> 7 a tail 0.0668 7 7 2
#> 8 a tail 0.100 8 8 3
# The frame numbers are kept, and become the index again
get_index(convert_unit_time(logged, "frame"))
#> [1] "frame"