The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
This vignette contains executable examples for the intended use of the R
package triact. Most of the functionalities are presented with
default parameters. We recommend that you also read the help pages to
learn more about the many parameters that can be used to customize the
behavior of the methods in triact. Furthermore, background and
rationale of the implemented analyses are described in detail in the
following publication:
Simmler M., Brouwers S. P., 2023. triact package for R: Analyzing the lying behavior of cows from accelerometer data, under review
Since triact is typically used with accelerometer data with
sampling frequency of ≥1 Hz, it is advisable to set R’s global option
digits.secs
to >=1 in order to enable the printing of
fractional seconds.
options(digits.secs = 1)
Via the global option triact_table
the type of tables
returned by triact can be specified. Options are
"data.frame"
(the default), "tibble"
, and
"data.table"
.
options(triact_table = "data.frame")
All functionalities of the triact R package are documented
on the help page of the Triact
R6 class.
?Triact
The triact R package includes two raw data files from triaxial
accelerometers (MSR145, MSR Electronics, Switzerland) attached to the
left hind leg of dairy cows. The sampling frequency was 5 Hz. Each file
represents one day of recording of one cow.
input_dir <- system.file("extdata", package = "triact")
files <- list.files(input_dir)
print(files)
## [1] "cow01_5hz.csv" "cow02_5hz.csv"
Inspecting one of the files reveals a file header and the
semicolon-separated data starting after the line with
"*Data
“. This is an example of what files imported by
triact might look like. However, triact can handle any
kind of delimiter-separated text files, with or without an arbitrary
file header (which is ignored during import).
cat(paste(readLines(file.path(input_dir, files[1]), n = 30), collapse = "\n"))
## *CREATOR
## msr_cutter.exe;[V6.06.02]
## msr2csv.exe;[V6.06.02]
##
## *STARTTIME
## 2021-06-29;06:00:00;
##
## *MODUL
## NAME;MSR314553;MSR314553;MSR314553
## *NAME
## NAME;6A;6A;6A
##
## ID;[C26113 V5.66];[C26113 V5.66];[C26113 V5.66]
##
## *CHANNEL
## TIME;ACC x;ACC y;ACC z
##
## *UNIT
## ;G;G;G
##
## *LIMITS
## ALARM;;;
## RECRD;;;
## LIMIT1;;;
## LIMIT2;;;
##
## *DATA
## 2021-06-29 06:00:00.055;-0.048;1.032;-0.063
## 2021-06-29 06:00:00.258;-0.048;1.000;-0.063
## 2021-06-29 06:00:00.461;-0.048;1.000;-0.063
The typical triact workflow starts by creating a new object
of the Triact
class.
my_triact <- Triact$new()
Acceleration data is then imported into the Triact
object (here named ‘my_triact’). The $load_files()
method
can be used to import any raw data files, which are delimiter-separated
text files. If you are starting with a new file format you may want to
select one or a few (small) files to find out how to specify the
method’s argument to enable correct import from the file(s). Once this
is done, you move on to process all your files. Examine your file format
in a plain text editor or in R (as above).
my_triact$load_files(input = input_dir,
id_substring = c(1, 5),
timeFwdUpRight_cols = c(1, -2, 3, -4),
time_format = "%Y-%m-%d %H:%M:%OS",
tz = "Europe/Zurich",
skip = "DATA",
sep = ";",
header = FALSE,
dec = ".")
The parameters as used above in the call of
$load_files()
have the following effects:
With id_substring = c(1, 5)
we specify which part of
the filenames represents the unique identifier of the cows, by
indicating the start and end character positions c(start, end). The
example files are named “cow01_5hz.csv” and “cow02_5hz.csv”. The
substring from the first to the fifth character can here serve as unique
identifier, therefore c(1, 5)
. Alternatively, we could have
used a perl-like regular expression that matches the substring
("^\\w{5}"
, see ?regex
).
With timeFwdUpRight_cols = c(1, -2, 3, -4)
we map
the columns as found in the files to the time, and the
forward, up, and right accelerations as
understood by triact. Fig. 1a shows the accelerometer used to
collect the example data with the axis directions as defined by the
manufacturer (XYZ). Fig. 1b shows the directions as used in
triact. To collect the example data, the accelerometer was
mounted to the outside of the left hind leg with the Y axis pointing in
Up direction, X in opposite direction of forward
(directed backwards), and Z in opposite direction of right
(directed left). In timeFwdUpRight_cols = c(1, -2, 3, -4)
,
the first number indicates in which column in the file the timestamp
(data-time) is located, here in the first column. The second number
indicates which column in the file maps to forward
acceleration, here the second column, but with negative mathematical
sign as X was pointing in the opposite direction of forward
(hence -2). The third number indicates which column in the file maps to
the up axis, here the third (the Y data). The last number
indicates which column in the file maps to the right
acceleration, here the fourth, but with opposite mathematical sign as Z
was pointing in the opposite direction of right (hence
-4).
With time_format = "%Y-%m-%d %H:%M:%OS"
we specify
the format of the timestamps as found in the files. The syntax is
described in ?strptime
.
With tz = "Europe/Zurich"
we specify the time zone
of the timestamps in the files. This is usually irrelevant if you do not
work across time zones as your system’s time zone is used as
default.
With skip = "DATA"
we specify the line in the files
to start reading data, here using a (sub)string of that line (see file
inspection above). Alternatively we could have used an integer
indicating the number of lines to skip before reading data.
With sep = ";"
we specify the separator character
that separates columns in the files.
With header = FALSE
we specify whether the first
column of the data (after considering skip) contains column
names.
Finally, with dec = "."
we specify the decimal
separator.
Of the optional arguments that specify details about your file format,
you may not need to specify many, because by default most of them are
inferred from the data. In the case of the example data, you can reduce
the arguments to:
my_triact$load_files(input = input_dir,
id_substring = c(1, 5),
timeFwdUpRight_cols = c(1, -2, 3, -4),
skip = "DATA")
Once the data has been imported, you can use the `$data’ field to inspect the imported raw data and (later) added analyses at any time during the workflow.
head(my_triact$data)
id | time | acc_fwd | acc_up | acc_right |
---|---|---|---|---|
cow01 | 2021-06-29 06:00:00.0 | 0.048 | 1.032 | 0.063 |
cow01 | 2021-06-29 06:00:00.2 | 0.048 | 1.000 | 0.063 |
cow01 | 2021-06-29 06:00:00.4 | 0.048 | 1.000 | 0.063 |
cow01 | 2021-06-29 06:00:00.6 | 0.048 | 1.032 | 0.063 |
cow01 | 2021-06-29 06:00:00.8 | 0.048 | 1.032 | 0.031 |
cow01 | 2021-06-29 06:00:01.0 | 0.079 | 1.032 | 0.031 |
str(my_triact$data)
## 'data.frame': 354462 obs. of 5 variables:
## $ id : Factor w/ 2 levels "cow01","cow02": 1 1 1 1 1 1 1 1 1 1 ...
## $ time : POSIXct, format: "2021-06-29 06:00:00.0" "2021-06-29 06:00:00.2" ...
## $ acc_fwd : num 0.048 0.048 0.048 0.048 0.048 0.079 0.048 0.048 0.079 0.079 ...
## $ acc_up : num 1.03 1 1 1.03 1.03 ...
## $ acc_right: num 0.063 0.063 0.063 0.063 0.031 0.031 0.031 0.031 0.031 0.031 ...
⚠️ Warning
Correct mapping of your data to the body relative direction as used
in triact is necessary for correct determination of the
lying/standing posture and the lying laterality (lying side). Therefore,
special care should be taken when specifying the parameter
timeFwdUpRight_cols
.
If you are unsure of the directions of your accelerometer’s XYZ data, you can determine them by experimentation. If the axis in question is pointing up, it should measure +1 g at rest. Note that accelerometers measure proper acceleration which is relative to free fall, so the gravitational components points skywards (reaction force of the ground).
ℹ NOTE 1
If you suspect that you have accidentally mounted some of your
accelerometers 180° rotated in the sagittal plane, but you don’t know
which raw data files are affected, you should call the
$check_orientation()
method after loading the data into the
Triact
object. This method will identify such “upside down”
data and correct it accordingly by multiplying the up and
forward axes by -1.
ℹ NOTE 2
You can import multiple files from the same cow, i.e., multiple files
with the same id as extracted from file names according to what you
specify via the id_substring
parameter. But the data with
the same cow id must follow each other without gaps in time. If you have
gaps, you should use unique ids for the time series without gaps,
e.g. you may need to use the cow identifier in combination with the date
as a unique id.
ℹ NOTE 3
It can take a long time to import many files. You can speed things up
by setting the parallel
parameter of
$load_files()
to > 1, which allows files to be read in
parallel. See ?Triact
for more information.
Alternatively to importing from raw data files with
load_files()
, you can read your files with your own routine
and then use the $load_table()
method to import a
data.frame into the Triact
object. Column names and data
types of the data.frame must be exactly as described in
?Triact
. An example data.frame, cows_5hz
, is
provided by the triact package.
A description of the example data.frame can be found on its help page.
?cows_5hz
str(cows_5hz)
## 'data.frame': 354462 obs. of 5 variables:
## $ id : Factor w/ 2 levels "cow01","cow02": 1 1 1 1 1 1 1 1 1 1 ...
## $ time : POSIXct, format: "2021-06-29 06:00:00.0" "2021-06-29 06:00:00.2" ...
## $ acc_fwd : num 0.048 0.048 0.048 0.048 0.048 0.079 0.048 0.048 0.079 0.079 ...
## $ acc_up : num 1.03 1 1 1.03 1.03 ...
## $ acc_right: num 0.063 0.063 0.063 0.063 0.031 0.031 0.031 0.031 0.031 0.031 ...
Create new Triact
object and import
cows_5hz
.
my_triact <- Triact$new()
my_triact$load_table(cows_5hz)
Calling add_… methods triggers analyses of lying behavior and the
calculation of proxies for the level of physical activity. The results
of the analyses are obtained for each time point of your accelerometer
data and added in new columns to the tabular data in the
Triact
object.
The $add_lying()
method performs the classification into
lying and standing posture. The results are (silently) added to the data
in the Triact
object as a logical column named
lying, where TRUE
indicates lying and
FALSE
standing. Additionally, lying and standing bouts are
uniquely numbered (per cow or ID) in column bout_nr.
my_triact$add_lying()
str(my_triact$data)
## 'data.frame': 354462 obs. of 7 variables:
## $ id : Factor w/ 2 levels "cow01","cow02": 1 1 1 1 1 1 1 1 1 1 ...
## $ time : POSIXct, format: "2021-06-29 06:00:00.0" "2021-06-29 06:00:00.2" ...
## $ acc_fwd : num 0.048 0.048 0.048 0.048 0.048 0.079 0.048 0.048 0.079 0.079 ...
## $ acc_up : num 1.03 1 1 1.03 1.03 ...
## $ acc_right: num 0.063 0.063 0.063 0.063 0.031 0.031 0.031 0.031 0.031 0.031 ...
## $ bout_nr : num 1 1 1 1 1 1 1 1 1 1 ...
## $ lying : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
ℹ NOTE
The $add_lying()
method comes with many parameters that
allow you to tweak the underlying algorithm. With the default
parameters, you can expect good results if your accelerometer sampling
frequency is ≥1 Hz. See ?Triact
and Simmler & Brouwers
(2023) for explanations.
The $add_side()
method performs the determination of
lying laterality (lying side). The results are (silently) added to the
data in the Triact
object as a factor column named
side, with levels ‘L’ (left) and ‘R’ (right). During standing
posture, side is NA
(not available). Crucial for
correct determination of the lying side is the correct specification of
which hind leg the accelerometer was mounted on (parameter
left_leg = TRUE
for left, or FALSE
for
right).
my_triact$add_side(left_leg = TRUE)
str(my_triact$data)
## 'data.frame': 354462 obs. of 8 variables:
## $ id : Factor w/ 2 levels "cow01","cow02": 1 1 1 1 1 1 1 1 1 1 ...
## $ time : POSIXct, format: "2021-06-29 06:00:00.0" "2021-06-29 06:00:00.2" ...
## $ acc_fwd : num 0.048 0.048 0.048 0.048 0.048 0.079 0.048 0.048 0.079 0.079 ...
## $ acc_up : num 1.03 1 1 1.03 1.03 ...
## $ acc_right: num 0.063 0.063 0.063 0.063 0.031 0.031 0.031 0.031 0.031 0.031 ...
## $ bout_nr : num 1 1 1 1 1 1 1 1 1 1 ...
## $ lying : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ side : Factor w/ 2 levels "L","R": NA NA NA NA NA NA NA NA NA NA ...
The $add_activity()
method performs the calculation of
proxies for the level of physical activity of the cow(s). By default,
the L2 norm of the vector of the dynamic body acceleration (DBA) is
calculated. It is ‘adjusted’ to a value of zero during lying bouts
(prefix Adj), i.e., periods when cows are lying are considered
as ‘inactive’ by definition. The results are (silently) added to the
data in the Triact
object as numeric column named
AdjL2DBA.
my_triact$add_activity()
str(my_triact$data)
## 'data.frame': 354462 obs. of 9 variables:
## $ id : Factor w/ 2 levels "cow01","cow02": 1 1 1 1 1 1 1 1 1 1 ...
## $ time : POSIXct, format: "2021-06-29 06:00:00.0" "2021-06-29 06:00:00.2" ...
## $ acc_fwd : num 0.048 0.048 0.048 0.048 0.048 0.079 0.048 0.048 0.079 0.079 ...
## $ acc_up : num 1.03 1 1 1.03 1.03 ...
## $ acc_right: num 0.063 0.063 0.063 0.063 0.031 0.031 0.031 0.031 0.031 0.031 ...
## $ bout_nr : num 1 1 1 1 1 1 1 1 1 1 ...
## $ lying : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ side : Factor w/ 2 levels "L","R": NA NA NA NA NA NA NA NA NA NA ...
## $ AdjL2DBA : num 0.0453 0.032 0.032 0.0453 0.032 ...
ℹ NOTE 1
You can select several proxies for the level of physical activity,
namely the L1 and L2 norms of DBA and Jerk. Use the norm
and dynamic_measure
parameters to do this. See Simmler
& Brouwers (2023) for a discussion of these proxies.
ℹ NOTE 2
Calculating DBA-based proxies involves a filtering step that can be
tuned with several parameters (see ?Triact
). With the
default parameters, you can expect good results if your accelerometer
sampling frequency is ≥1 Hz.
The $summarize… methods are used to summarize the analyses added to
the Triact
object per time period, representing either the
standing/lying bouts or regular intervals, e.g. 1 h or 24 h.
With $summarize_bouts()
a summary is created for the
individual lying and standing bouts, with duration, mean activity, and
lying side (for a lying bout). There is a help page with a description
of the output.
?bout_summary
bouts_summary <- my_triact$summarize_bouts()
In the output you can see that the first bout per cow is not
completely observed (startTime
is missing) and therefor NAs
are returned for measures that depend on complete observation of the
bout, e.g. duration.
head(bouts_summary)
id | bout_nr | startTime | endTime | duration | lying | side | meanAdjL2DBA |
---|---|---|---|---|---|---|---|
cow01 | 1 | NA | 2021-06-29 06:17:40.3 | NA | FALSE | NA | NA |
cow01 | 2 | 2021-06-29 06:17:40.3 | 2021-06-29 07:07:16.3 | 49.59968 | TRUE | L | 0.0000000 |
cow01 | 3 | 2021-06-29 07:07:16.3 | 2021-06-29 09:11:33.2 | 124.28197 | FALSE | NA | 0.2076106 |
cow01 | 4 | 2021-06-29 09:11:33.2 | 2021-06-29 09:46:51.8 | 35.30985 | TRUE | R | 0.0000000 |
cow01 | 5 | 2021-06-29 09:46:51.8 | 2021-06-29 12:44:45.8 | 177.90022 | FALSE | NA | 0.0844073 |
cow01 | 6 | 2021-06-29 12:44:45.8 | 2021-06-29 14:18:29.8 | 93.73198 | TRUE | R | 0.0000000 |
If only the lying bouts are of interest, the bout_type
parameter can be specified accordingly.
bouts_summary <- my_triact$summarize_bouts(bout_type = "lying")
You can see that the last lying bout of cow01 and the first lying
bout of cow02 were incompletely observed (startTime
and
endTime
missing, respectively). Again, NAs are returned for
measures that depend on complete observation of the bout.
head(bouts_summary)
id | bout_nr | startTime | endTime | duration | lying | side | meanAdjL2DBA |
---|---|---|---|---|---|---|---|
cow01 | 2 | 2021-06-29 06:17:40.3 | 2021-06-29 07:07:16.3 | 49.59968 | TRUE | L | 0 |
cow01 | 4 | 2021-06-29 09:11:33.2 | 2021-06-29 09:46:51.8 | 35.30985 | TRUE | R | 0 |
cow01 | 6 | 2021-06-29 12:44:45.8 | 2021-06-29 14:18:29.8 | 93.73198 | TRUE | R | 0 |
cow01 | 8 | 2021-06-29 14:23:35.9 | NA | NA | TRUE | L | NA |
cow02 | 1 | NA | 2021-06-29 07:07:26.9 | NA | TRUE | R | NA |
cow02 | 3 | 2021-06-29 12:56:43.3 | 2021-06-29 14:38:01.0 | 101.29500 | TRUE | R | 0 |
ℹ NOTE
When calling the $summarize_bouts()
method with
parameter calc_for_incomplete = TRUE
, a complete summary is
also returned for the incompletely observed bouts (first and last bout
for each cow). It does this by simply assuming that the bouts were
completely observed. Use this option with caution.
With $summarize_intervals()
the summary is obtained per
regular intervals, by default per hour. There is a help page with a
description of the output.
?interval_summary
int_summary <- my_triact$summarize_intervals()
The NAs in the output are a result of incompletely observed intervals
(first and last interval of each cow). The NaN on the other hand do not
indicate missing information: For example, if the cow was not standing
in the interval, the mean activity during standing is not zero, but
cannot be calculated (thus NaN, “not a number”).
head(int_summary)
id | startTime | centerTime | endTime | duration | durationStanding | durationLying | durationLyingLeft | durationLyingRight | meanAdjL2DBA | meanAdjL2DBALying | meanAdjL2DBAStanding |
---|---|---|---|---|---|---|---|---|---|---|---|
cow01 | 2021-06-29 06:00:00 | 2021-06-29 06:30:00 | 2021-06-29 07:00:00 | NA | NA | NA | NA | NA | NA | NA | NA |
cow01 | 2021-06-29 07:00:00 | 2021-06-29 07:30:00 | 2021-06-29 08:00:00 | 59.99968 | 52.72782 | 7.271868 | 7.271868 | 0.00000 | 0.2373473 | 0 | 0.2700807 |
cow01 | 2021-06-29 08:00:00 | 2021-06-29 08:30:00 | 2021-06-29 09:00:00 | 59.99970 | 59.99970 | 0.000000 | 0.000000 | 0.00000 | 0.1678524 | NaN | 0.1678524 |
cow01 | 2021-06-29 09:00:00 | 2021-06-29 09:30:00 | 2021-06-29 10:00:00 | 60.00307 | 24.69321 | 35.309861 | 0.000000 | 35.30986 | 0.0485225 | 0 | 0.1179069 |
cow01 | 2021-06-29 10:00:00 | 2021-06-29 10:30:00 | 2021-06-29 11:00:00 | 59.99970 | 59.99970 | 0.000000 | 0.000000 | 0.00000 | 0.1016988 | NaN | 0.1016988 |
cow01 | 2021-06-29 11:00:00 | 2021-06-29 11:30:00 | 2021-06-29 12:00:00 | 59.99968 | 59.99968 | 0.000000 | 0.000000 | 0.00000 | 0.0603954 | NaN | 0.0603954 |
str(int_summary)
## 'data.frame': 20 obs. of 12 variables:
## $ id : Factor w/ 2 levels "cow01","cow02": 1 1 1 1 1 1 1 1 1 1 ...
## $ startTime : POSIXct, format: "2021-06-29 06:00:00" "2021-06-29 07:00:00" ...
## $ centerTime : POSIXct, format: "2021-06-29 06:30:00" "2021-06-29 07:30:00" ...
## $ endTime : POSIXct, format: "2021-06-29 07:00:00" "2021-06-29 08:00:00" ...
## $ duration : num NA 60 60 60 60 ...
## $ durationStanding : num NA 52.7 60 24.7 60 ...
## $ durationLying : num NA 7.27 0 35.31 0 ...
## $ durationLyingLeft : num NA 7.27 0 0 0 ...
## $ durationLyingRight : num NA 0 0 35.3 0 ...
## $ meanAdjL2DBA : num NA 0.2373 0.1679 0.0485 0.1017 ...
## $ meanAdjL2DBALying : num NA 0 NaN 0 NaN NaN 0 0 0 NA ...
## $ meanAdjL2DBAStanding: num NA 0.27 0.168 0.118 0.102 ...
The intervals can be specified quite flexibly: In case of 30 min
intervals and starting 10 min after the full hour you can specify
interval
and lag_in_s
parameters
accordingly.
int_summary <- my_triact$summarize_intervals(interval = "30 min",
lag_in_s = 10 * 60)
head(int_summary)
id | startTime | centerTime | endTime | duration | durationStanding | durationLying | durationLyingLeft | durationLyingRight | meanAdjL2DBA | meanAdjL2DBALying | meanAdjL2DBAStanding |
---|---|---|---|---|---|---|---|---|---|---|---|
cow01 | 2021-06-29 05:40:00 | 2021-06-29 05:55:00 | 2021-06-29 06:10:00 | NA | NA | NA | NA | NA | NA | NA | NA |
cow01 | 2021-06-29 06:10:00 | 2021-06-29 06:25:00 | 2021-06-29 06:40:00 | 30.00152 | 7.671342 | 22.33017 | 22.33017 | 0 | 0.0341027 | 0 | 0.1333706 |
cow01 | 2021-06-29 06:40:00 | 2021-06-29 06:55:00 | 2021-06-29 07:10:00 | 29.99812 | 2.728640 | 27.26948 | 27.26948 | 0 | 0.0557571 | 0 | 0.6129823 |
cow01 | 2021-06-29 07:10:00 | 2021-06-29 07:25:00 | 2021-06-29 07:40:00 | 30.00152 | 30.001517 | 0.00000 | 0.00000 | 0 | 0.2730567 | NaN | 0.2730567 |
cow01 | 2021-06-29 07:40:00 | 2021-06-29 07:55:00 | 2021-06-29 08:10:00 | 29.99813 | 29.998133 | 0.00000 | 0.00000 | 0 | 0.2080457 | NaN | 0.2080457 |
cow01 | 2021-06-29 08:10:00 | 2021-06-29 08:25:00 | 2021-06-29 08:40:00 | 30.00150 | 30.001500 | 0.00000 | 0.00000 | 0 | 0.1756038 | NaN | 0.1756038 |
str(int_summary)
## 'data.frame': 42 obs. of 12 variables:
## $ id : Factor w/ 2 levels "cow01","cow02": 1 1 1 1 1 1 1 1 1 1 ...
## $ startTime : POSIXct, format: "2021-06-29 05:40:00" "2021-06-29 06:10:00" ...
## $ centerTime : POSIXct, format: "2021-06-29 05:55:00" "2021-06-29 06:25:00" ...
## $ endTime : POSIXct, format: "2021-06-29 06:10:00" "2021-06-29 06:40:00" ...
## $ duration : num NA 30 30 30 30 ...
## $ durationStanding : num NA 7.67 2.73 30 30 ...
## $ durationLying : num NA 22.3 27.3 0 0 ...
## $ durationLyingLeft : num NA 22.3 27.3 0 0 ...
## $ durationLyingRight : num NA 0 0 0 0 ...
## $ meanAdjL2DBA : num NA 0.0341 0.0558 0.2731 0.208 ...
## $ meanAdjL2DBALying : num NA 0 0 NaN NaN NaN NaN 0 0 NaN ...
## $ meanAdjL2DBAStanding: num NA 0.133 0.613 0.273 0.208 ...
With bouts = TRUE
you can request that, additionally, the
bouts within the intervals are summarized. For measures such as the
number of lying bouts or mean lying bout duration, a weighted mean is
calculated with the weights being the proportion of the individual bout
overlapping with the respective interval. With side = TRUE
you can additionally request a differentiation of all results by lying
side. Again, NAs in the output are a result of incompletely observed
intervals (first and last interval of each cow). Additionally you will
sometimes find NAs in the output for summaries of bouts per interval
(bouts = TRUE
) that result from incompletely observed bouts
(first and last bout for each cow). As bouts can span several intervals,
this can affect more than just the first and the last interval. Please
be aware about the difference between NA and NaN described above.
int_summary <- my_triact$summarize_intervals(bouts = TRUE,
side = TRUE)
str(int_summary)
## 'data.frame': 20 obs. of 22 variables:
## $ id : Factor w/ 2 levels "cow01","cow02": 1 1 1 1 1 1 1 1 1 1 ...
## $ startTime : POSIXct, format: "2021-06-29 06:00:00" "2021-06-29 07:00:00" ...
## $ centerTime : POSIXct, format: "2021-06-29 06:30:00" "2021-06-29 07:30:00" ...
## $ endTime : POSIXct, format: "2021-06-29 07:00:00" "2021-06-29 08:00:00" ...
## $ duration : num NA 60 60 60 60 ...
## $ durationStanding : num NA 52.7 60 24.7 60 ...
## $ durationLying : num NA 7.27 0 35.31 0 ...
## $ durationLyingLeft : num NA 7.27 0 0 0 ...
## $ durationLyingRight : num NA 0 0 35.3 0 ...
## $ meanAdjL2DBA : num NA 0.2373 0.1679 0.0485 0.1017 ...
## $ meanAdjL2DBALying : num NA 0 NaN 0 NaN NaN 0 0 0 NA ...
## $ meanAdjL2DBAStanding : num NA 0.27 0.168 0.118 0.102 ...
## $ meanAdjL2DBALyingLeft : num NA 0 NaN NaN NaN NaN NaN NaN 0 NA ...
## $ meanAdjL2DBALyingRight : num NA NaN NaN 0 NaN NaN 0 0 0 NA ...
## $ nBoutsStanding : num NA 0.424 0.483 0.167 0.337 ...
## $ nBoutsLying : num NA 0.147 0 1 0 ...
## $ nBoutsLyingLeft : num NA 0.147 0 0 0 ...
## $ nBoutsLyingRight : num NA 0 0 1 0 ...
## $ wMeanDurationStandingBout : num NA 124 124 148 178 ...
## $ wMeanDurationLyingBout : num NA 49.6 NaN 35.3 NaN ...
## $ wMeanDurationLyingBoutLeft : num NA 49.6 NaN NaN NaN ...
## $ wMeanDurationLyingBoutRight: num NA NaN NaN 35.3 NaN ...
ℹ NOTE
When calling the $summarize_intervals()
method with
parameter calc_for_incomplete = TRUE
, a complete summary
will also be returned for the incompletely observed intervals (first and
last interval for each cow) and for any parameter using information of
incompletely observed bouts (which can affect more than just the first
and last interval). It does this by simply assuming that intervals and
bouts were completely observed. Use this option with caution.
The triact package does not come with visualization
capabilities. But the data can easily be accessed and plotted with base
R or packages dedicated to graphics (e.g. ggplot2). The following
example shows how to access the data of a single cow (here with id
“cow01”) and to visualize the lying behavior.
cow_id = "cow01"
data_01 <- my_triact$data[my_triact$data$id == cow_id, ]
plot(!lying ~ time, data = data_01,
type = "l", ylab = "", yaxt = "n", bty = "n")
lines(ifelse(side == "R", 0, NA) ~ time, data = data_01, col = "orange")
lines(ifelse(side == "L", 0, NA) ~ time, data = data_01, col = "purple")
axis(2, at = c(0, 1),
labels = c("lying", "standing"),
las = 1,
lwd = 0)
legend(x = "center",
legend = c("right", "left"),
col = c("orange", "purple"),
lwd = 1, bty = "n", title = "lying side")
Using $extract_liedown()
and
$extract_standup()
, the raw acceleration data (and added
analyses) of the posture transitions, i.e., lying-to-standing and
standing-to-lying, can be extracted.
With default parameters, only the time of the transition, bout nr of the lying bout, and lying side (if available) are returned.
st_ups <- my_triact$extract_standup()
print(st_ups)
## id time bout_nr side
## 1 cow01 2021-06-29 07:07:16 2 L
## 2 cow01 2021-06-29 09:46:51 4 R
## 3 cow01 2021-06-29 14:18:29 6 R
## 4 cow01 2021-06-29 15:29:43 8 L
## 5 cow02 2021-06-29 07:07:26 1 R
## 6 cow02 2021-06-29 14:38:00 3 R
## 7 cow02 2021-06-29 15:43:00 5 L
When specifying ‘sec_before’ and ’sec_after`, time series around the exact moment of posture transition as detected by triact are returned. The result is a list with tables (one table per posture transition).
l_downs <- my_triact$extract_liedown(sec_before = 3, sec_after = 3)
head(l_downs[[1]])
id | time | acc_fwd | acc_up | acc_right | bout_nr | lying | side | AdjL2DBA |
---|---|---|---|---|---|---|---|---|
cow01 | 2021-06-29 06:17:37.5 | 0.238 | 0.968 | 0.031 | 1 | FALSE | NA | 0.0992975 |
cow01 | 2021-06-29 06:17:37.7 | 0.175 | 0.968 | 0.031 | 1 | FALSE | NA | 0.0989798 |
cow01 | 2021-06-29 06:17:37.9 | 0.175 | 1.000 | 0.000 | 1 | FALSE | NA | 0.1327027 |
cow01 | 2021-06-29 06:17:38.1 | 0.143 | 1.000 | 0.063 | 1 | FALSE | NA | 0.0940053 |
cow01 | 2021-06-29 06:17:38.3 | 0.143 | 1.000 | 0.063 | 1 | FALSE | NA | 0.0940053 |
cow01 | 2021-06-29 06:17:38.5 | 0.111 | 1.032 | 0.031 | 1 | FALSE | NA | 0.1481789 |
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.