The goal of whippr
is to provide a set of tools for manipulating gas exchange data from cardiopulmonary exercise testing.
Why whippr
?
The name of the package is in honor of Prof. Brian J Whipp and his invaluable contribution to the field of exercise physiology.
Installation
You can install the development version of whippr
from Github with:
# install.packages("remotes")
remotes::install_github("fmmattioni/whippr")
Use
Read data
library(whippr)
## example file that comes with the package for demonstration purposes
path_example <- system.file("example_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: 754 × 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 2 8.08 1.19 9.60 380. 301. 185. 52.9 25.3 31.9 4.58
#> 2 4 23.2 0.915 21.2 864. 665. 141. 40.8 24.5 31.9 10.4
#> 3 8 15.6 2.11 32.9 1317. 1075. 325. 97.2 25.0 30.6 15.9
#> 4 11 20.6 1.18 24.4 894. 714. 188. 49.2 27.3 34.1 10.8
#> 5 14 23.3 0.947 22.1 822. 647. 150. 39.4 26.9 34.1 9.90
#> 6 18 14.7 2.28 33.6 1347. 1126. 351. 108. 24.9 29.8 16.2
#> 7 23 11.2 2.32 26.1 980. 848. 364. 107. 26.6 30.7 11.8
#> 8 28 13.2 2.18 28.8 1147. 981. 336. 105. 25.2 29.4 13.8
#> 9 31 17.7 1.51 26.7 1048. 860. 234. 68.8 25.5 31.0 12.6
#> 10 35 14.2 1.68 23.8 973. 794. 257. 79.3 24.5 30.0 11.7
#> # ℹ 744 more rows
#> # ℹ 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>, …
Interpolate
df %>%
interpolate()
#> # Metabolic cart: COSMED
#> # Data status: interpolated data
#> # Time column: t
#> # A tibble: 2,159 × 114
#> 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 2 8.08 1.19 9.60 380. 301. 185. 52.9 25.3 31.9 4.58
#> 2 3 15.6 1.05 15.4 622. 483. 163. 46.8 24.9 31.9 7.50
#> 3 4 23.2 0.915 21.2 864. 665. 141. 40.8 24.5 31.9 10.4
#> 4 5 21.3 1.21 24.1 978. 767. 187. 54.9 24.6 31.6 11.8
#> 5 6 19.4 1.51 27.1 1091. 870. 233. 69.0 24.8 31.3 13.1
#> 6 7 17.5 1.81 30.0 1204. 973. 279. 83.1 24.9 30.9 14.5
#> 7 8 15.6 2.11 32.9 1317. 1075. 325. 97.2 25.0 30.6 15.9
#> 8 9 17.3 1.80 30.1 1176. 955. 279. 81.2 25.7 31.8 14.2
#> 9 10 19.0 1.49 27.2 1035. 834. 233. 65.2 26.5 33.0 12.5
#> 10 11 20.6 1.18 24.4 894. 714. 188. 49.2 27.3 34.1 10.8
#> # ℹ 2,149 more rows
#> # ℹ 103 more variables: R <dbl>, FeO2 <dbl>, FeCO2 <dbl>, HR <dbl>,
#> # `VO2/HR` <dbl>, Load1 <dbl>, Load2 <dbl>, Load3 <dbl>, Phase <dbl>,
#> # 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>, …
Perform averages
Bin-average
## example of performing 30-s bin-averages
df %>%
interpolate() %>%
perform_average(type = "bin", bins = 30)
#> # Metabolic cart: COSMED
#> # Data status: averaged data - 30-s bins
#> # Time column: t
#> # A tibble: 73 × 114
#> 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 19.0 1.33 24.0 932. 744. 207. 58.9 25.8 32.5 11.2
#> 2 30 15.3 1.85 27.1 1097. 904. 284. 87.0 24.8 30.1 13.2
#> 3 60 19.6 1.47 27.1 1133. 892. 223. 69.6 24.1 30.7 13.7
#> 4 90 13.3 2.29 26.0 1043. 885. 353. 111. 24.9 29.5 12.6
#> 5 120 20.5 1.43 27.1 1107. 883. 218. 66.9 24.6 31.0 13.3
#> 6 150 14.4 1.57 22.1 928. 751. 239. 75.5 24.1 29.7 11.2
#> 7 180 23.0 1.18 26.4 1071. 849. 180. 54.4 24.8 31.3 12.9
#> 8 210 16.1 2.17 28.7 1070. 941. 342. 101. 27.0 30.6 12.9
#> 9 240 18.9 1.43 26.1 1058. 880. 219. 68.8 24.7 29.8 12.7
#> 10 270 15.1 1.65 24.5 987. 847. 253. 81.4 24.8 28.9 11.9
#> # ℹ 63 more rows
#> # ℹ 103 more variables: R <dbl>, FeO2 <dbl>, FeCO2 <dbl>, HR <dbl>,
#> # `VO2/HR` <dbl>, Load1 <dbl>, Load2 <dbl>, Load3 <dbl>, Phase <dbl>,
#> # 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>, …
Rolling-average
## example of performing 30-s rolling-averages
df %>%
interpolate() %>%
perform_average(type = "rolling", rolling_window = 30)
#> # Metabolic cart: COSMED
#> # Data status: averaged data - 30-s rolling average
#> # Time column: t
#> # A tibble: 2,130 × 114
#> 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 16.5 16.4 1.75 26.5 1033. 852. 271. 80.1 25.7 31.3 12.4
#> 2 17.5 16.6 1.76 27.0 1054. 870. 273. 80.7 25.7 31.3 12.7
#> 3 18.5 16.7 1.78 27.3 1067. 882. 276. 81.6 25.7 31.3 12.9
#> 4 19.5 16.4 1.80 27.4 1071. 887. 280. 82.8 25.7 31.2 12.9
#> 5 20.5 16.2 1.82 27.4 1071. 888. 282. 83.6 25.7 31.1 12.9
#> 6 21.5 16.0 1.82 27.3 1068. 885. 282. 83.8 25.7 31.1 12.9
#> 7 22.5 16.0 1.81 27.1 1062. 880. 280. 83.4 25.7 31.1 12.8
#> 8 23.5 16.0 1.78 26.9 1052. 871. 277. 82.4 25.6 31.0 12.7
#> 9 24.5 16.1 1.77 26.7 1048. 867. 274. 81.8 25.5 31.0 12.6
#> 10 25.5 16.1 1.76 26.6 1050. 868. 273. 81.9 25.4 30.8 12.6
#> # ℹ 2,120 more rows
#> # ℹ 103 more variables: R <dbl>, FeO2 <dbl>, FeCO2 <dbl>, HR <dbl>,
#> # `VO2/HR` <dbl>, Load1 <dbl>, Load2 <dbl>, Load3 <dbl>, Phase <dbl>,
#> # 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>, …
Perform VO2 kinetics analysis
results_kinetics <- vo2_kinetics(
.data = df,
intensity_domain = "moderate",
vo2_column = "VO2",
protocol_n_transitions = 3,
protocol_baseline_length = 360,
protocol_transition_length = 360,
cleaning_level = 0.95,
cleaning_baseline_fit = c("linear", "exponential", "exponential"),
fit_level = 0.95,
fit_bin_average = 5,
fit_phase_1_length = 20,
fit_baseline_length = 120,
fit_transition_length = 240,
verbose = TRUE
)
#> ────────────────────────── * V̇O₂ kinetics analysis * ─────────────────────────
#> ✔ Detecting outliers
#> • 14 outliers found in transition 1
#> • 15 outliers found in transition 2
#> • 13 outliers found in transition 3
#> ✔ Processing data...
#> ✔ └─ Removing outliers
#> ✔ └─ Interpolating each transition
#> ✔ └─ Ensemble-averaging transitions
#> ✔ └─ Performing 5-s bin averages
#> ✔ Fitting data...
#> ✔ └─ Fitting baseline
#> ✔ └─ Fitting transition
#> ✔ └─ Calculating residuals
#> ✔ └─ Preparing plots
#> ────────────────────────────────── * DONE * ──────────────────────────────────
Perform VO2max analysis
df_incremental <- read_data(path = system.file("ramp_cosmed.xlsx", package = "whippr"), metabolic_cart = "cosmed")
vo2_max(
.data = df_incremental, ## 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 × 6
#> VO2max_absolute VO2max_relative POpeak HRmax RERmax plot
#> <dbl> <dbl> <int> <dbl> <dbl> <list>
#> 1 3524. 46.0 303 193 1.13 <gg>
Metabolic carts currently supported
- COSMED
- CORTEX
- NSpire
- Parvo Medics
- Geratherm Respiratory
- CardioCoach
Online app
Would you like to perform VO2 kinetics analyses but don’t know R? No problem! You can use our online app: VO2 Kinetics App
Code of Conduct
Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
Icons made by monkik from www.flaticon.com