If you have an incremental test, whippr
can also help you out! In this vignette you will learn how to:
All of the above work both in a ramp and in a step incremental test.
To get started, let’s read in the example data from a ramp incremental test that comes with the package. This is a test that had the following protocol:
library(whippr)
library(ggplot2)
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
path_example <- system.file("ramp_cosmed.xlsx", package = "whippr")
df <- read_data(path = path_example, metabolic_cart = "cosmed")
df
#> # Metabolic cart: COSMED
#> # Data status: raw data
#> # Time column: t
#> # A tibble: 390 x 119
#> t Rf VT VE VO2 VCO2 O2exp CO2exp `VE/VO2` `VE/VCO2` `VO2/Kg`
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 0 23.3 0.808 18.8 654. 579. 131. 34.6 28.7 32.4 8.53
#> 2 6 9.45 3.09 29.2 1111. 1038. 488. 152. 26.3 28.1 14.5
#> 3 10 14.3 1.87 26.8 1064. 963. 291. 93.4 25.2 27.8 13.9
#> 4 15 14.2 2.05 29.1 1136. 1032. 321. 101. 25.6 28.2 14.8
#> 5 19 13.4 2.05 27.5 1083. 999. 319. 103. 25.4 27.5 14.1
#> 6 24 13.3 2.08 27.7 1104. 1021. 323. 106. 25.1 27.2 14.4
#> 7 28 14.0 1.78 25.0 1017. 948. 274. 93.8 24.6 26.3 13.3
#> 8 33 11.4 2.11 24.2 971. 919. 326. 111. 24.9 26.3 12.7
#> 9 38 13.2 2.00 26.5 1008. 973. 315. 102. 26.3 27.2 13.1
#> 10 43 11.5 2.09 23.9 921. 904. 326. 109. 25.9 26.4 12.0
#> # … with 380 more rows, and 108 more variables: R <dbl>, FeO2 <dbl>,
#> # FeCO2 <dbl>, HR <dbl>, `VO2/HR` <dbl>, Load1 <dbl>, Load2 <dbl>,
#> # Load3 <dbl>, Phase <dbl>, Marker <lgl>, FetO2 <dbl>, FetCO2 <dbl>,
#> # FiO2 <dbl>, FiCO2 <dbl>, Ti <dbl>, Te <dbl>, Ttot <dbl>, `Ti/Ttot` <dbl>,
#> # IV <dbl>, PetO2 <dbl>, PetCO2 <dbl>, `P(a-et)CO2` <dbl>, SpO2 <dbl>,
#> # `VD(phys)` <dbl>, `VD/VT` <dbl>, `Env. Temp.` <dbl>, `Analyz. Temp.` <dbl>,
#> # `Analyz. Press.` <dbl>, `Env. Press.` <dbl>, Batteries <dbl>, PaCO2 <dbl>,
#> # PaO2 <dbl>, PH <dbl>, SaO2 <dbl>, `HCO3-` <dbl>, `Bias Flow` <dbl>,
#> # `La-` <dbl>, Hb <dbl>, `Steady State` <chr>, EEm <dbl>, EEh <dbl>,
#> # EEkc <dbl>, EEbsa <dbl>, EEkg <dbl>, PROg <dbl>, PROkc <dbl>, FATg <dbl>,
#> # FATkc <dbl>, CHOg <dbl>, CHOkc <dbl>, `PRO%` <dbl>, `FAT%` <dbl>,
#> # `CHO%` <dbl>, npRQ <dbl>, `t Rel` <dbl>, `mark Speed` <dbl>, `mark
#> # Dist.` <dbl>, `ST I` <dbl>, `ST II` <dbl>, `ST III` <dbl>, `ST aVR` <dbl>,
#> # `ST aVL` <dbl>, `ST aVF` <dbl>, `ST V1` <dbl>, `ST V2` <dbl>, `ST
#> # V3` <dbl>, `ST V4` <dbl>, `ST V5` <dbl>, `ST V6` <dbl>, `S I` <dbl>, `S
#> # II` <dbl>, `S III` <dbl>, `S aVR` <dbl>, `S aVL` <dbl>, `S aVF` <dbl>, `S
#> # V1` <dbl>, `S V2` <dbl>, `S V3` <dbl>, `S V4` <dbl>, `S V5` <dbl>, `S
#> # V6` <dbl>, `P Syst` <dbl>, `P Diast` <dbl>, Symptom <dbl>, DP <dbl>,
#> # Stage <dbl>, RR <dbl>, METS <dbl>, `Phase time` <chr>, Qt <dbl>, SV <dbl>,
#> # `Vt/FVC` <dbl>, Long <chr>, Lat <chr>, Alt <dbl>, `GPS Speed` <dbl>, `GPS
#> # Dist.` <dbl>, predVO2 <dbl>, BR <dbl>, `O2 Cost` <dbl>, …
df %>%
ggplot(aes(t, VO2)) +
geom_point(shape = 21, size = 4, fill = "white") +
theme_whippr()
A few things to note:
All of the above will be fixed with the incremental_normalize()
function. Since we do not have a work rate column, we will set the argument work_rate_magic = TRUE
. This argument will allow us to calculate the work rates throughout the test.
ramp_normalized <- df %>%
incremental_normalize(
.data = .,
incremental_type = "ramp",
has_baseline = TRUE,
baseline_length = 240, ## 4-min baseline
work_rate_magic = TRUE,
baseline_intensity = 20, ## baseline was performed at 20 W
ramp_increase = 25 ## 25 W/min ramp
)
ramp_normalized
#> # Metabolic cart: COSMED
#> # Data status: raw data - ramp normalized
#> # Time column: t
#> # Test type: incremental
#> # Protocol: 240-s baseline at 20 W and a 25-W/min ramp
#> # A tibble: 390 x 121
#> t Rf VT VE VO2 VCO2 O2exp CO2exp `VE/VO2` `VE/VCO2` `VO2/Kg`
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 -240 23.3 0.808 18.8 654. 579. 131. 34.6 28.7 32.4 8.53
#> 2 -234 9.45 3.09 29.2 1111. 1038. 488. 152. 26.3 28.1 14.5
#> 3 -230 14.3 1.87 26.8 1064. 963. 291. 93.4 25.2 27.8 13.9
#> 4 -225 14.2 2.05 29.1 1136. 1032. 321. 101. 25.6 28.2 14.8
#> 5 -221 13.4 2.05 27.5 1083. 999. 319. 103. 25.4 27.5 14.1
#> 6 -216 13.3 2.08 27.7 1104. 1021. 323. 106. 25.1 27.2 14.4
#> 7 -212 14.0 1.78 25.0 1017. 948. 274. 93.8 24.6 26.3 13.3
#> 8 -207 11.4 2.11 24.2 971. 919. 326. 111. 24.9 26.3 12.7
#> 9 -202 13.2 2.00 26.5 1008. 973. 315. 102. 26.3 27.2 13.1
#> 10 -197 11.5 2.09 23.9 921. 904. 326. 109. 25.9 26.4 12.0
#> # … with 380 more rows, and 110 more variables: R <dbl>, FeO2 <dbl>,
#> # FeCO2 <dbl>, HR <dbl>, `VO2/HR` <dbl>, Load1 <dbl>, Load2 <dbl>,
#> # Load3 <dbl>, Phase <dbl>, Marker <lgl>, FetO2 <dbl>, FetCO2 <dbl>,
#> # FiO2 <dbl>, FiCO2 <dbl>, Ti <dbl>, Te <dbl>, Ttot <dbl>, `Ti/Ttot` <dbl>,
#> # IV <dbl>, PetO2 <dbl>, PetCO2 <dbl>, `P(a-et)CO2` <dbl>, SpO2 <dbl>,
#> # `VD(phys)` <dbl>, `VD/VT` <dbl>, `Env. Temp.` <dbl>, `Analyz. Temp.` <dbl>,
#> # `Analyz. Press.` <dbl>, `Env. Press.` <dbl>, Batteries <dbl>, PaCO2 <dbl>,
#> # PaO2 <dbl>, PH <dbl>, SaO2 <dbl>, `HCO3-` <dbl>, `Bias Flow` <dbl>,
#> # `La-` <dbl>, Hb <dbl>, `Steady State` <chr>, EEm <dbl>, EEh <dbl>,
#> # EEkc <dbl>, EEbsa <dbl>, EEkg <dbl>, PROg <dbl>, PROkc <dbl>, FATg <dbl>,
#> # FATkc <dbl>, CHOg <dbl>, CHOkc <dbl>, `PRO%` <dbl>, `FAT%` <dbl>,
#> # `CHO%` <dbl>, npRQ <dbl>, `t Rel` <dbl>, `mark Speed` <dbl>, `mark
#> # Dist.` <dbl>, `ST I` <dbl>, `ST II` <dbl>, `ST III` <dbl>, `ST aVR` <dbl>,
#> # `ST aVL` <dbl>, `ST aVF` <dbl>, `ST V1` <dbl>, `ST V2` <dbl>, `ST
#> # V3` <dbl>, `ST V4` <dbl>, `ST V5` <dbl>, `ST V6` <dbl>, `S I` <dbl>, `S
#> # II` <dbl>, `S III` <dbl>, `S aVR` <dbl>, `S aVL` <dbl>, `S aVF` <dbl>, `S
#> # V1` <dbl>, `S V2` <dbl>, `S V3` <dbl>, `S V4` <dbl>, `S V5` <dbl>, `S
#> # V6` <dbl>, `P Syst` <dbl>, `P Diast` <dbl>, Symptom <dbl>, DP <dbl>,
#> # Stage <dbl>, RR <dbl>, METS <dbl>, `Phase time` <chr>, Qt <dbl>, SV <dbl>,
#> # `Vt/FVC` <dbl>, Long <chr>, Lat <chr>, Alt <dbl>, `GPS Speed` <dbl>, `GPS
#> # Dist.` <dbl>, predVO2 <dbl>, BR <dbl>, `O2 Cost` <dbl>, …
We can see that now our data is aware of the two different phases in the test: baseline and ramp period:
ramp_normalized %>%
distinct(protocol_phase)
#> # Metabolic cart: COSMED
#> # Data status: raw data - ramp normalized
#> # Time column: t
#> # Test type: incremental
#> # Protocol: 240-s baseline at 20 W and a 25-W/min ramp
#> # A tibble: 2 x 1
#> protocol_phase
#> <chr>
#> 1 baseline
#> 2 ramp
Additionally, a new column was created: work_rate
:
ramp_normalized %>%
select(t, work_rate)
#> # Metabolic cart: COSMED
#> # Data status: raw data - ramp normalized
#> # Time column: t
#> # Test type: incremental
#> # Protocol: 240-s baseline at 20 W and a 25-W/min ramp
#> # A tibble: 390 x 2
#> t work_rate
#> <dbl> <dbl>
#> 1 -240 20
#> 2 -234 20
#> 3 -230 20
#> 4 -225 20
#> 5 -221 20
#> 6 -216 20
#> 7 -212 20
#> 8 -207 20
#> 9 -202 20
#> 10 -197 20
#> # … with 380 more rows
And we can also plot it to check what was done. Note that there is a constant-load during baseline (20 W), and then a constant increase in power output (25 W/min) during the ramp phase:
ramp_normalized %>%
plot_incremental()
We can therefore quickly analyze our peak power output as:
ramp_normalized %>%
slice_max(work_rate) %>%
select(work_rate)
#> # Metabolic cart: COSMED
#> # Data status: raw data - ramp normalized
#> # Time column: t
#> # Test type: incremental
#> # Protocol: 240-s baseline at 20 W and a 25-W/min ramp
#> # A tibble: 1 x 1
#> work_rate
#> <dbl>
#> 1 303.
But what if we had a step-incremental test? How does the work rate transformation work? In a step test is important to have both the actual power output from each step, and also a linearization of the power output. To illustrate what I mean, let’s take a look at an example:
## get file path from example data
path_example_step <- system.file("step_cortex.xlsx", package = "whippr")
## read data from step test
df_step <- read_data(path = path_example_step, metabolic_cart = "cortex")
df_step
#> # Metabolic cart: CORTEX
#> # Data status: raw data
#> # Time column: t
#> # A tibble: 792 x 29
#> t VT AF `V'E (BTPS)` `V'max (BTPS)` FEetO2 FEetCO2 PetO2 PetCO2
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 4.8 0.72 18.5 13.3 0.42 15.9 4.6 106. 30.8
#> 2 7.9 0.76 19.4 14.7 0.46 16.0 4.63 107. 31
#> 3 10.9 0.77 19.9 15.3 0.47 16.0 4.74 107. 31.7
#> 4 13.9 0.76 20 15.1 0.47 16.2 4.65 109. 31.1
#> 5 17.5 0.95 16.7 15.8 0.49 16.1 4.76 108. 31.8
#> 6 20.9 0.83 17.5 14.6 0.56 16.5 4.54 110. 30.4
#> 7 24.3 0.75 17.8 13.3 0.45 16.5 4.54 110. 30.4
#> 8 28.2 0.8 15.3 12.3 0.42 16.3 4.69 109. 31.4
#> 9 31.9 0.8 16.5 13.1 0.48 16.4 4.56 110. 30.5
#> 10 35.7 0.72 15.8 11.5 0.43 16.2 4.7 109. 31.4
#> # … with 782 more rows, and 20 more variables: `V'O2 (STPD)` <dbl>,
#> # `V'CO2` <dbl>, R <dbl>, `V'O2/kg` <dbl>, METS <dbl>, `V'E/V'O2` <dbl>,
#> # `V'E/V'CO2` <dbl>, `VD/VT (est)` <dbl>, HF <dbl>, La <chr>, W <dbl>,
#> # EU <dbl>, `EU/kg` <dbl>, CHO <dbl>, FETT <dbl>, EFF <chr>, `%AR` <dbl>,
#> # `V'O2/kg_Lean` <dbl>, `EE/kg_Lean` <dbl>, AR <dbl>
Note that our data contains weird column names. So, for simplicity, let’s rename the VO2 column.
df_step_renamed <- df_step %>%
rename(VO2 = `V'O2 (STPD)`)
That is a test that had the following protocol:
df_step_renamed %>%
ggplot(aes(t, VO2)) +
geom_point(shape = 21, size = 4, fill = "white") +
theme_whippr()
So, let’s first normalize our data:
step_normalized <- df_step %>%
incremental_normalize(
.data = .,
incremental_type = "step",
has_baseline = TRUE,
baseline_length = 120, ## 2 min baseline
work_rate_magic = TRUE,
baseline_intensity = 0, ## baseline was resting on the bike, so intensity is 0 W
step_start = 50, ## step protocol started at 50 W
step_increase = 25, ## step increase was 25 W
step_length = 180 ## the intensity increased every 3 minutes
)
step_normalized
#> # Metabolic cart: CORTEX
#> # Data status: raw data - step normalized
#> # Time column: t
#> # Test type: incremental
#> # Protocol: 120-s baseline at 0 W and 180-s steps of 25 W starting at 50 W
#> # A tibble: 792 x 33
#> t VT AF `V'E (BTPS)` `V'max (BTPS)` FEetO2 FEetCO2 PetO2 PetCO2
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 -115. 0.72 18.5 13.3 0.42 15.9 4.6 106. 30.8
#> 2 -112. 0.76 19.4 14.7 0.46 16.0 4.63 107. 31
#> 3 -109. 0.77 19.9 15.3 0.47 16.0 4.74 107. 31.7
#> 4 -106. 0.76 20 15.1 0.47 16.2 4.65 109. 31.1
#> 5 -102. 0.95 16.7 15.8 0.49 16.1 4.76 108. 31.8
#> 6 -99.1 0.83 17.5 14.6 0.56 16.5 4.54 110. 30.4
#> 7 -95.7 0.75 17.8 13.3 0.45 16.5 4.54 110. 30.4
#> 8 -91.8 0.8 15.3 12.3 0.42 16.3 4.69 109. 31.4
#> 9 -88.1 0.8 16.5 13.1 0.48 16.4 4.56 110. 30.5
#> 10 -84.3 0.72 15.8 11.5 0.43 16.2 4.7 109. 31.4
#> # … with 782 more rows, and 24 more variables: `V'O2 (STPD)` <dbl>,
#> # `V'CO2` <dbl>, R <dbl>, `V'O2/kg` <dbl>, METS <dbl>, `V'E/V'O2` <dbl>,
#> # `V'E/V'CO2` <dbl>, `VD/VT (est)` <dbl>, HF <dbl>, La <chr>, W <dbl>,
#> # EU <dbl>, `EU/kg` <dbl>, CHO <dbl>, FETT <dbl>, EFF <chr>, `%AR` <dbl>,
#> # `V'O2/kg_Lean` <dbl>, `EE/kg_Lean` <dbl>, AR <dbl>, protocol_phase <chr>,
#> # work_rate <dbl>, step_work_rate <dbl>, step <fct>
And then we can visualize what was done with the work rate with the plot_incremental()
function:
step_normalized %>%
plot_incremental()
As you can note, two working rates were created: one with the actual power output, and another one with the linearization of the power output.
step_normalized %>%
select(t, protocol_phase:step)
#> # Metabolic cart: CORTEX
#> # Data status: raw data - step normalized
#> # Time column: t
#> # Test type: incremental
#> # Protocol: 120-s baseline at 0 W and 180-s steps of 25 W starting at 50 W
#> # A tibble: 792 x 5
#> t protocol_phase work_rate step_work_rate step
#> <dbl> <chr> <dbl> <dbl> <fct>
#> 1 -115. baseline 0 0 step_0
#> 2 -112. baseline 0 0 step_0
#> 3 -109. baseline 0 0 step_0
#> 4 -106. baseline 0 0 step_0
#> 5 -102. baseline 0 0 step_0
#> 6 -99.1 baseline 0 0 step_0
#> 7 -95.7 baseline 0 0 step_0
#> 8 -91.8 baseline 0 0 step_0
#> 9 -88.1 baseline 0 0 step_0
#> 10 -84.3 baseline 0 0 step_0
#> # … with 782 more rows
This is useful, for example, to calculate the peak power output:
step_normalized %>%
slice_max(work_rate) %>%
select(work_rate)
#> # Metabolic cart: CORTEX
#> # Data status: raw data - step normalized
#> # Time column: t
#> # Test type: incremental
#> # Protocol: 120-s baseline at 0 W and 180-s steps of 25 W starting at 50 W
#> # A tibble: 1 x 1
#> work_rate
#> <dbl>
#> 1 252.
As you might have noticed, these two incremental test examples had a few bad breaths (outliers) that should be deleted prior to any data analysis. This can be easily achieved with the detect_outliers()
function.
Two methods for detecting outliers are available: linear and anomaly detection. The linear method is going to fit two linear models: one for the baseline period, and another one for the ramp (or step) period. The anomaly detection, however, uses the anomalize package, which decompose time series, and then perform the anomaly detection. Let’s see it in action:
## detect ramp outliers
data_ramp_outliers <- detect_outliers(
.data = ramp_normalized,
test_type = "incremental",
vo2_column = "VO2",
cleaning_level = 0.95,
method_incremental = "linear",
verbose = TRUE
)
#> ✔ Detecting outliers
#> ● 2 outlier(s) found in baseline
#> ● 15 outlier(s) found in ramp
data_ramp_outliers
#> # Metabolic cart: COSMED
#> # Data status: raw data - outliers detected
#> # Time column: t
#> # VO2 column: VO2
#> # Test type: incremental
#> # Protocol: 240-s baseline at 20 W and a 25-W/min ramp
#> # A tibble: 390 x 134
#> t Rf VT VE VO2 VCO2 O2exp CO2exp `VE/VO2` `VE/VCO2` `VO2/Kg`
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 -240 23.3 0.808 18.8 654. 579. 131. 34.6 28.7 32.4 8.53
#> 2 -234 9.45 3.09 29.2 1111. 1038. 488. 152. 26.3 28.1 14.5
#> 3 -230 14.3 1.87 26.8 1064. 963. 291. 93.4 25.2 27.8 13.9
#> 4 -225 14.2 2.05 29.1 1136. 1032. 321. 101. 25.6 28.2 14.8
#> 5 -221 13.4 2.05 27.5 1083. 999. 319. 103. 25.4 27.5 14.1
#> 6 -216 13.3 2.08 27.7 1104. 1021. 323. 106. 25.1 27.2 14.4
#> 7 -212 14.0 1.78 25.0 1017. 948. 274. 93.8 24.6 26.3 13.3
#> 8 -207 11.4 2.11 24.2 971. 919. 326. 111. 24.9 26.3 12.7
#> 9 -202 13.2 2.00 26.5 1008. 973. 315. 102. 26.3 27.2 13.1
#> 10 -197 11.5 2.09 23.9 921. 904. 326. 109. 25.9 26.4 12.0
#> # … with 380 more rows, and 123 more variables: R <dbl>, FeO2 <dbl>,
#> # FeCO2 <dbl>, HR <dbl>, `VO2/HR` <dbl>, Load1 <dbl>, Load2 <dbl>,
#> # Load3 <dbl>, Phase <dbl>, Marker <lgl>, FetO2 <dbl>, FetCO2 <dbl>,
#> # FiO2 <dbl>, FiCO2 <dbl>, Ti <dbl>, Te <dbl>, Ttot <dbl>, `Ti/Ttot` <dbl>,
#> # IV <dbl>, PetO2 <dbl>, PetCO2 <dbl>, `P(a-et)CO2` <dbl>, SpO2 <dbl>,
#> # `VD(phys)` <dbl>, `VD/VT` <dbl>, `Env. Temp.` <dbl>, `Analyz. Temp.` <dbl>,
#> # `Analyz. Press.` <dbl>, `Env. Press.` <dbl>, Batteries <dbl>, PaCO2 <dbl>,
#> # PaO2 <dbl>, PH <dbl>, SaO2 <dbl>, `HCO3-` <dbl>, `Bias Flow` <dbl>,
#> # `La-` <dbl>, Hb <dbl>, `Steady State` <chr>, EEm <dbl>, EEh <dbl>,
#> # EEkc <dbl>, EEbsa <dbl>, EEkg <dbl>, PROg <dbl>, PROkc <dbl>, FATg <dbl>,
#> # FATkc <dbl>, CHOg <dbl>, CHOkc <dbl>, `PRO%` <dbl>, `FAT%` <dbl>,
#> # `CHO%` <dbl>, npRQ <dbl>, `t Rel` <dbl>, `mark Speed` <dbl>, `mark
#> # Dist.` <dbl>, `ST I` <dbl>, `ST II` <dbl>, `ST III` <dbl>, `ST aVR` <dbl>,
#> # `ST aVL` <dbl>, `ST aVF` <dbl>, `ST V1` <dbl>, `ST V2` <dbl>, `ST
#> # V3` <dbl>, `ST V4` <dbl>, `ST V5` <dbl>, `ST V6` <dbl>, `S I` <dbl>, `S
#> # II` <dbl>, `S III` <dbl>, `S aVR` <dbl>, `S aVL` <dbl>, `S aVF` <dbl>, `S
#> # V1` <dbl>, `S V2` <dbl>, `S V3` <dbl>, `S V4` <dbl>, `S V5` <dbl>, `S
#> # V6` <dbl>, `P Syst` <dbl>, `P Diast` <dbl>, Symptom <dbl>, DP <dbl>,
#> # Stage <dbl>, RR <dbl>, METS <dbl>, `Phase time` <chr>, Qt <dbl>, SV <dbl>,
#> # `Vt/FVC` <dbl>, Long <chr>, Lat <chr>, Alt <dbl>, `GPS Speed` <dbl>, `GPS
#> # Dist.` <dbl>, predVO2 <dbl>, BR <dbl>, `O2 Cost` <dbl>, …
data_ramp_outliers %>%
plot_outliers()
Thereafter, you can easily remove the detected outliers like this:
data_ramp_outliers %>%
filter(outlier == "no")
#> # Metabolic cart: COSMED
#> # Data status: raw data - outliers detected
#> # Time column: t
#> # VO2 column: VO2
#> # Test type: incremental
#> # Protocol: 240-s baseline at 20 W and a 25-W/min ramp
#> # A tibble: 373 x 134
#> t Rf VT VE VO2 VCO2 O2exp CO2exp `VE/VO2` `VE/VCO2` `VO2/Kg`
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 -240 23.3 0.808 18.8 654. 579. 131. 34.6 28.7 32.4 8.53
#> 2 -234 9.45 3.09 29.2 1111. 1038. 488. 152. 26.3 28.1 14.5
#> 3 -230 14.3 1.87 26.8 1064. 963. 291. 93.4 25.2 27.8 13.9
#> 4 -225 14.2 2.05 29.1 1136. 1032. 321. 101. 25.6 28.2 14.8
#> 5 -221 13.4 2.05 27.5 1083. 999. 319. 103. 25.4 27.5 14.1
#> 6 -216 13.3 2.08 27.7 1104. 1021. 323. 106. 25.1 27.2 14.4
#> 7 -212 14.0 1.78 25.0 1017. 948. 274. 93.8 24.6 26.3 13.3
#> 8 -207 11.4 2.11 24.2 971. 919. 326. 111. 24.9 26.3 12.7
#> 9 -202 13.2 2.00 26.5 1008. 973. 315. 102. 26.3 27.2 13.1
#> 10 -197 11.5 2.09 23.9 921. 904. 326. 109. 25.9 26.4 12.0
#> # … with 363 more rows, and 123 more variables: R <dbl>, FeO2 <dbl>,
#> # FeCO2 <dbl>, HR <dbl>, `VO2/HR` <dbl>, Load1 <dbl>, Load2 <dbl>,
#> # Load3 <dbl>, Phase <dbl>, Marker <lgl>, FetO2 <dbl>, FetCO2 <dbl>,
#> # FiO2 <dbl>, FiCO2 <dbl>, Ti <dbl>, Te <dbl>, Ttot <dbl>, `Ti/Ttot` <dbl>,
#> # IV <dbl>, PetO2 <dbl>, PetCO2 <dbl>, `P(a-et)CO2` <dbl>, SpO2 <dbl>,
#> # `VD(phys)` <dbl>, `VD/VT` <dbl>, `Env. Temp.` <dbl>, `Analyz. Temp.` <dbl>,
#> # `Analyz. Press.` <dbl>, `Env. Press.` <dbl>, Batteries <dbl>, PaCO2 <dbl>,
#> # PaO2 <dbl>, PH <dbl>, SaO2 <dbl>, `HCO3-` <dbl>, `Bias Flow` <dbl>,
#> # `La-` <dbl>, Hb <dbl>, `Steady State` <chr>, EEm <dbl>, EEh <dbl>,
#> # EEkc <dbl>, EEbsa <dbl>, EEkg <dbl>, PROg <dbl>, PROkc <dbl>, FATg <dbl>,
#> # FATkc <dbl>, CHOg <dbl>, CHOkc <dbl>, `PRO%` <dbl>, `FAT%` <dbl>,
#> # `CHO%` <dbl>, npRQ <dbl>, `t Rel` <dbl>, `mark Speed` <dbl>, `mark
#> # Dist.` <dbl>, `ST I` <dbl>, `ST II` <dbl>, `ST III` <dbl>, `ST aVR` <dbl>,
#> # `ST aVL` <dbl>, `ST aVF` <dbl>, `ST V1` <dbl>, `ST V2` <dbl>, `ST
#> # V3` <dbl>, `ST V4` <dbl>, `ST V5` <dbl>, `ST V6` <dbl>, `S I` <dbl>, `S
#> # II` <dbl>, `S III` <dbl>, `S aVR` <dbl>, `S aVL` <dbl>, `S aVF` <dbl>, `S
#> # V1` <dbl>, `S V2` <dbl>, `S V3` <dbl>, `S V4` <dbl>, `S V5` <dbl>, `S
#> # V6` <dbl>, `P Syst` <dbl>, `P Diast` <dbl>, Symptom <dbl>, DP <dbl>,
#> # Stage <dbl>, RR <dbl>, METS <dbl>, `Phase time` <chr>, Qt <dbl>, SV <dbl>,
#> # `Vt/FVC` <dbl>, Long <chr>, Lat <chr>, Alt <dbl>, `GPS Speed` <dbl>, `GPS
#> # Dist.` <dbl>, predVO2 <dbl>, BR <dbl>, `O2 Cost` <dbl>, …
Note that we set 95% of confidence level when detecting the outliers. You can easily change that, for example, to 99%:
detect_outliers(
.data = ramp_normalized,
test_type = "incremental",
vo2_column = "VO2",
cleaning_level = 0.99, ## changed to 99%
method_incremental = "linear",
verbose = TRUE
) %>%
plot_outliers()
#> ✔ Detecting outliers
#> ● 8 outlier(s) found in ramp
Now let’s see how the anomaly detection performs:
detect_outliers(
.data = ramp_normalized,
test_type = "incremental",
vo2_column = "VO2",
cleaning_level = 0.95,
method_incremental = "anomaly", ## changed to anomaly detection
verbose = TRUE
) %>%
plot_outliers()
#> ✔ Detecting outliers
#> Registered S3 method overwritten by 'quantmod':
#> method from
#> as.zoo.data.frame zoo
#> ● 6 outlier(s) found in ramp
There are two functions that you can use to analyze VO2max:
vo2_max()
: it performs all the necessary steps, which include:
incremental_normalize()
: normalize incremental test datadetect_outliers()
: detect outliersinterpolate()
: interpolate data from breath-by-breath into second-by-secondperform_average()
: perform average on second-by-second dataperform_max()
: it only performs the final steps (interpolate()
and perform_average()
).perform_max()
results_vo2max <- data_ramp_outliers %>% ## data was already normalized and outliers were detected
perform_max(
.data = .,
vo2_column = "VO2",
vo2_relative_column = "VO2/Kg",
heart_rate_column = "HR",
rer_column = "R",
average_method = "bin",
average_length = 30,
plot = TRUE,
verbose = FALSE
)
results_vo2max
#> # A tibble: 1 x 6
#> VO2max_absolute VO2max_relative POpeak HRmax RERmax plot
#> <dbl> <dbl> <int> <dbl> <dbl> <list>
#> 1 3524. 46.0 303 193 1.13 <gg>
results_vo2max$plot[[1]]
vo2_max()
vo2_max(
.data = df, ## data from `read_data()`
vo2_column = "VO2",
vo2_relative_column = "VO2/Kg",
heart_rate_column = "HR",
rer_column = "R",
detect_outliers = TRUE,
average_method = "bin",
average_length = 30,
plot = TRUE,
verbose = TRUE,
## arguments for `incremental_normalize()`
incremental_type = "ramp",
has_baseline = TRUE,
baseline_length = 240, ## 4-min baseline
work_rate_magic = TRUE, ## produce a work rate column
baseline_intensity = 20, ## baseline was performed at 20 W
ramp_increase = 25, ## 25 W/min ramp
## arguments for `detect_outliers()`
test_type = "incremental",
cleaning_level = 0.95,
method_incremental = "linear"
)
#> ──────────────────────────── * V̇O₂ max analysis * ───────────────────────────
#> ✔ Normalizing incremental data...
#> ✔ Detecting outliers
#> ● 2 outlier(s) found in baseline
#> ● 15 outlier(s) found in ramp
#> ✔ Filtering out outliers...
#> ✔ Interpolating from breath-by-breath into second-by-second...
#> ✔ Performing averages...
#> # A tibble: 1 x 6
#> VO2max_absolute VO2max_relative POpeak HRmax RERmax plot
#> <dbl> <dbl> <int> <dbl> <dbl> <list>
#> 1 3524. 46.0 303 193 1.13 <gg>