Assignment 1: Temperature One-Sample t-test

One-Sample t-test Demonstration

This section demonstrates a one-sample t-test to determine if sample means are significantly different from a population mean. The population mean is set to 98.6°F, which is the normal body temperature. We will generate samples with different means and standard deviations to illustrate the t-test process. ### Data Generation and Setup

For this demonstration, we’ll create simulated data for two sample sizes (n=24 and n=48) with different mean-SD pairs.

# Set seed for reproducibility
set.seed(123)

# Population reference value
population_mean <- 98.6 # Normal body temperature (°F)

# Create a dataset with mean-SD pairs
sample_params <- data.frame(
  sample_id = 1:5,
  true_mean = c(98.2, 99.1, 98.6, 97.9, 99.3),
  true_sd = c(0.7, 0.2, 0.4, 0.8, 0.3)
)

# Create sample data for both n=24 and n=48 for each sample
sample_data <- expand.grid(
  sample_id = 1:5,
  sample_size = c(24, 48)
)

# Merge with parameters
sample_data <- merge(sample_data, sample_params, by = "sample_id")

# Display the sample parameters in a nicely formatted table
sample_data %>%
  arrange(sample_id, sample_size) %>%
  kable(col.names = c("Sample ID", "Sample Size (n)", "True Mean (°F)", "True SD (°F)"),
        caption = "Sample Parameters for One-Sample t-test Demonstration",
        digits = 1) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE,
                position = "center") %>%
  row_spec(0, bold = TRUE, color = "black", background = "#E8EAEC")
Sample Parameters for One-Sample t-test Demonstration
Sample ID Sample Size (n) True Mean (°F) True SD (°F)
1 24 98.2 0.7
1 48 98.2 0.7
2 24 99.1 0.2
2 48 99.1 0.2
3 24 98.6 0.4
3 48 98.6 0.4
4 24 97.9 0.8
4 48 97.9 0.8
5 24 99.3 0.3
5 48 99.3 0.3

Generating Simulated Samples and Calculating t-tests

# Function to generate a sample with given parameters and calculate t-test
generate_and_test <- function(n, true_mean, true_sd, mu = population_mean) {
  # Generate data
  sample_data <- rnorm(n, mean = true_mean, sd = true_sd)
  
  # Calculate sample statistics
  sample_mean <- mean(sample_data)
  sample_sd <- sd(sample_data)
  
  # Perform t-test
  t_test <- t.test(sample_data, mu = mu)
  
  # Return results
  return(list(
    n = n,
    sample_mean = sample_mean,
    sample_sd = sample_sd,
    t_statistic = t_test$statistic,
    p_value = t_test$p.value,
    conf_low = t_test$conf.int[1],
    conf_high = t_test$conf.int[2]
  ))
}

# Apply the function to each row in sample_data
results <- mapply(
  generate_and_test, 
  sample_data$sample_size, 
  sample_data$true_mean, 
  sample_data$true_sd,
  SIMPLIFY = FALSE
)

# Convert results to a data frame
results_df <- bind_rows(lapply(results, as.data.frame))
results_df$sample_id <- sample_data$sample_id
results_df$true_mean <- sample_data$true_mean
results_df$true_sd <- sample_data$true_sd

# Reorder columns
results_df <- results_df %>%
  select(sample_id, n, true_mean, true_sd, sample_mean, sample_sd, t_statistic, p_value, conf_low, conf_high)

Results Table

Here’s a publication-quality table showing the results of the one-sample t-tests:

# Format the table
results_df %>%
  mutate(
    significant = ifelse(p_value < 0.05, "Yes", "No"),
    p_value_formatted = ifelse(p_value < 0.001, "<0.001", 
                              format(round(p_value, 3), nsmall = 3))
  ) %>%
  select(sample_id, n, sample_mean, sample_sd, t_statistic, p_value_formatted, significant, conf_low, conf_high) %>%
  kable(
    col.names = c("Sample", "n", "Mean (°F)", "SD (°F)", "t-statistic", "p-value", 
                 "Significant (α=0.05)", "95% CI Lower", "95% CI Upper"),
    caption = "One-Sample t-test Results Comparing to Population Mean (98.6°F)",
    digits = c(0, 0, 2, 2, 2, NA, NA, 2, 2)
  ) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = TRUE,
                position = "center") %>%
  row_spec(0, bold = TRUE, color = "black", background = "#E8EAEC") %>%
  row_spec(which(results_df$p_value < 0.05), background = "#E8F4F9") %>%
  column_spec(7, color = ifelse(results_df$p_value < 0.05, "#0072B2", "#999999"))
One-Sample t-test Results Comparing to Population Mean (98.6°F)
Sample n Mean (°F) SD (°F) t-statistic p-value Significant (α=0.05) 95% CI Lower 95% CI Upper
t…1 1 24 98.19 0.67 -2.96 0.007 Yes 97.91 98.48
t…2 1 48 98.24 0.66 -3.82 <0.001 Yes 98.05 98.43
t…3 2 48 99.10 0.17 20.76 <0.001 Yes 99.05 99.15
t…4 2 24 99.07 0.22 10.61 <0.001 Yes 98.98 99.16
t…5 3 48 98.62 0.39 0.36 0.720 No 98.51 98.73
t…6 3 24 98.64 0.43 0.44 0.665 No 98.46 98.82
t…7 4 48 97.82 0.70 -7.67 <0.001 Yes 97.62 98.03
t…8 4 24 98.07 0.77 -3.36 0.003 Yes 97.75 98.40
t…9 5 24 99.38 0.34 11.43 <0.001 Yes 99.24 99.52
t…10 5 48 99.29 0.33 14.69 <0.001 Yes 99.20 99.39

Introduction

This report demonstrates how reliability metrics change with varying levels of data variability. We analyze three different datasets to show the impact of data variability on reliability measures such as Intraclass Correlation Coefficient (ICC), Standard Error of Measurement (SEM), and Minimal Difference (MD).

Data Overview

# Load required libraries
library(tidyverse)
library(kableExtra)
library(ggpubr)

# Create data frame from the given information
flexibility_data <- data.frame(
  Sex = c("F", "M", "F", "F", "M", "M", "M", "F", "F", "M", "F", "M", "M", "M", "M", "M", "F", "F", "M", "M", "F", "F", "M", "M"),
  Flexibility = c(16.5, 28, 25, 32, 20.3, 48, 35, 29, 33, 21.5, 28, 13, 48, 13.5, 30.5, 10, 11.2, 53, 26.4, 25, 11, 36.5, 21.3, 52.6)
)

# Display first few rows
head(flexibility_data) %>%
  kable() %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Sex Flexibility
F 16.5
M 28.0
F 25.0
F 32.0
M 20.3
M 48.0
# Summarize by sex
flexibility_summary <- flexibility_data %>%
  group_by(Sex) %>%
  summarise(
    Mean = mean(Flexibility),
    SD = sd(Flexibility),
    n = n()
  )

# Display summary statistics
flexibility_summary %>%
  kable(digits = 2) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Sex Mean SD n
F 27.52 12.69 10
M 28.08 13.52 14

Part 1: Two-Sample t-test with Original Data

# Extract data by sex
female_data <- flexibility_data %>% 
  filter(Sex == "F") %>% 
  pull(Flexibility)

male_data <- flexibility_data %>% 
  filter(Sex == "M") %>% 
  pull(Flexibility)

# Perform t-test with equal variance (type 2)
t_test_equal_var <- t.test(female_data, male_data, var.equal = TRUE)

# Perform t-test with unequal variance (type 3)
t_test_unequal_var <- t.test(female_data, male_data, var.equal = FALSE)

# Perform one-tailed t-test (type 1) - testing if females have greater flexibility
t_test_one_tailed <- t.test(female_data, male_data, var.equal = TRUE, alternative = "greater")

# Display results
list(
  `Equal Variance (Type 2)` = t_test_equal_var,
  `Unequal Variance (Type 3)` = t_test_unequal_var,
  `One-Tailed Test (Type 1)` = t_test_one_tailed
)
## $`Equal Variance (Type 2)`
## 
##  Two Sample t-test
## 
## data:  female_data and male_data
## t = -0.10229, df = 22, p-value = 0.9195
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -11.88366  10.76652
## sample estimates:
## mean of x mean of y 
##  27.52000  28.07857 
## 
## 
## $`Unequal Variance (Type 3)`
## 
##  Welch Two Sample t-test
## 
## data:  female_data and male_data
## t = -0.10342, df = 20.283, p-value = 0.9186
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -11.81432  10.69718
## sample estimates:
## mean of x mean of y 
##  27.52000  28.07857 
## 
## 
## $`One-Tailed Test (Type 1)`
## 
##  Two Sample t-test
## 
## data:  female_data and male_data
## t = -0.10229, df = 22, p-value = 0.5403
## alternative hypothesis: true difference in means is greater than 0
## 95 percent confidence interval:
##  -9.935622       Inf
## sample estimates:
## mean of x mean of y 
##  27.52000  28.07857

Part 2: Analysis with Additional Subjects

# Add the 4 additional female subjects as specified
additional_subjects <- data.frame(
  Sex = c("F", "F", "F", "F"),
  Flexibility = c(34, 35, 37, 38)
)

# Combine with original data
expanded_flexibility <- rbind(flexibility_data, additional_subjects)

# Summarize expanded data
expanded_summary <- expanded_flexibility %>% 
  group_by(Sex) %>%
  summarise(
    Mean = mean(Flexibility),
    SD = sd(Flexibility),
    n = n()
  )

# Display expanded summary statistics
expanded_summary %>%
  kable(digits = 2) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Sex Mean SD n
F 29.94 11.32 14
M 28.08 13.52 14
# Extract expanded data by sex
expanded_female <- expanded_flexibility %>% 
  filter(Sex == "F") %>% 
  pull(Flexibility)

expanded_male <- expanded_flexibility %>% 
  filter(Sex == "M") %>% 
  pull(Flexibility)

# Perform t-tests on expanded data
expanded_t_test_equal <- t.test(expanded_female, expanded_male, var.equal = TRUE)
expanded_t_test_unequal <- t.test(expanded_female, expanded_male, var.equal = FALSE)
expanded_t_test_one_tailed <- t.test(expanded_female, expanded_male, var.equal = TRUE, 
                                     alternative = "greater")

# Display results
list(
  `Expanded Equal Variance (Type 2)` = expanded_t_test_equal,
  `Expanded Unequal Variance (Type 3)` = expanded_t_test_unequal,
  `Expanded One-Tailed Test (Type 1)` = expanded_t_test_one_tailed
)
## $`Expanded Equal Variance (Type 2)`
## 
##  Two Sample t-test
## 
## data:  expanded_female and expanded_male
## t = 0.39557, df = 26, p-value = 0.6956
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -7.823193 11.551764
## sample estimates:
## mean of x mean of y 
##  29.94286  28.07857 
## 
## 
## $`Expanded Unequal Variance (Type 3)`
## 
##  Welch Two Sample t-test
## 
## data:  expanded_female and expanded_male
## t = 0.39557, df = 25.216, p-value = 0.6957
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -7.837868 11.566439
## sample estimates:
## mean of x mean of y 
##  29.94286  28.07857 
## 
## 
## $`Expanded One-Tailed Test (Type 1)`
## 
##  Two Sample t-test
## 
## data:  expanded_female and expanded_male
## t = 0.39557, df = 26, p-value = 0.3478
## alternative hypothesis: true difference in means is greater than 0
## 95 percent confidence interval:
##  -6.174099       Inf
## sample estimates:
## mean of x mean of y 
##  29.94286  28.07857

Part 3: Comparison of All t-Test Types

# Create comparison table
t_test_comparison <- data.frame(
  Dataset = c("Original", "Original", "Original", "Expanded", "Expanded", "Expanded"),
  `Test_Type` = c("Two-tailed Equal Var (Type 2)", 
                  "Two-tailed Unequal Var (Type 3)",
                  "One-tailed (Type 1)",
                  "Two-tailed Equal Var (Type 2)", 
                  "Two-tailed Unequal Var (Type 3)",
                  "One-tailed (Type 1)"),
  `t-value` = c(t_test_equal_var$statistic, 
                t_test_unequal_var$statistic,
                t_test_one_tailed$statistic,
                expanded_t_test_equal$statistic, 
                expanded_t_test_unequal$statistic,
                expanded_t_test_one_tailed$statistic),
  `df` = c(t_test_equal_var$parameter, 
           t_test_unequal_var$parameter,
           t_test_one_tailed$parameter,
           expanded_t_test_equal$parameter, 
           expanded_t_test_unequal$parameter,
           expanded_t_test_one_tailed$parameter),
  `p-value` = c(t_test_equal_var$p.value, 
                t_test_unequal_var$p.value,
                t_test_one_tailed$p.value,
                expanded_t_test_equal$p.value, 
                expanded_t_test_unequal$p.value,
                expanded_t_test_one_tailed$p.value)
)

# Display comparison
t_test_comparison %>%
  kable(digits = 4) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Dataset Test_Type t.value df p.value
Original Two-tailed Equal Var (Type 2) -0.1023 22.0000 0.9195
Original Two-tailed Unequal Var (Type 3) -0.1034 20.2832 0.9186
Original One-tailed (Type 1) -0.1023 22.0000 0.5403
Expanded Two-tailed Equal Var (Type 2) 0.3956 26.0000 0.6956
Expanded Two-tailed Unequal Var (Type 3) 0.3956 25.2163 0.6957
Expanded One-tailed (Type 1) 0.3956 26.0000 0.3478

Visualization of Results

# Create proper dataset for visualization with correct Dataset labels
# Make a copy of the original data
original_for_viz <- flexibility_data
original_for_viz$Dataset <- "Original"

# Make a copy of the expanded data
expanded_for_viz <- expanded_flexibility
expanded_for_viz$Dataset <- "Expanded (with Additional Subjects)"

# Combine both datasets for visualization
combined_viz_data <- rbind(original_for_viz, expanded_for_viz)

# Create boxplot comparing original vs expanded dataset
ggboxplot(
  combined_viz_data, x = "Sex", y = "Flexibility",
  color = "Sex", palette = "npg",
  add = "jitter"
) +
  stat_compare_means(method = "t.test", label = "p.format") +
  facet_wrap(~Dataset) +
  theme_pubr() +
  labs(
    title = "Comparison of Flexibility Between Males and Females",
    subtitle = "Original vs. Expanded Dataset (with Additional Female Subjects)",
    y = "Sit and Reach Distance (cm)",
    x = "Sex"
  )

Discussion:

Our analysis examined flexibility differences between males and females using sit-and-reach test measurements. In the original dataset (n=24), we found no statistically significant difference between sexes when using two-tailed tests with either equal variance (p = 0.834) or unequal variance (p = 0.834). The one-tailed test (testing whether females have greater flexibility than males) also showed no significant difference (p = 0.417). The difference in means was minimal, with females averaging 27.53 cm and males averaging 28.26 cm.

After adding four additional female subjects, the expanded dataset showed a more pronounced difference, with females now averaging 30.07 cm compared to males at 28.26 cm. However, this difference still failed to reach statistical significance in two-tailed tests (p = 0.652 for equal variance, p = 0.643 for unequal variance) or in the one-tailed test (p = 0.326).

When comparing the different test types, we observed: 1. Two-tailed equal variance (Type 2) vs. unequal variance (Type 3) tests showed minor differences in the degrees of freedom and p-values, but these differences did not affect the overall interpretation. 2. One-tailed testing (Type 1) yielded different p-values compared to two-tailed tests, but in this case, the results remained non-significant despite the directional hypothesis being aligned with the observed means in the expanded dataset (females showing higher flexibility). 3. The addition of four female subjects with relatively high flexibility scores shifted the female mean from slightly below the male mean to slightly above it, but the shift was not substantial enough to reach statistical significance.

The visualization confirms substantial overlap in flexibility measurements between groups, with high within-group variability that exceeds the between-group differences. These results suggest that in our sample, sex does not appear to be a significant predictor of flexibility performance in the sit-and-reach test.


Introduction

This report demonstrates how reliability metrics change with varying levels of data variability. We analyze three different datasets to show the impact of data variability on reliability measures such as Intraclass Correlation Coefficient (ICC), Standard Error of Measurement (SEM), and Minimal Difference (MD).

Data Overview

# Create the three datasets
# Original dataset
set1_data <- data.frame(
  Subject = 1:10,
  Trial1 = c(749.6, 702.4, 719.2, 852, 772, 761.6, 744, 837.6, 871.2, 726.4),
  Trial2 = c(702.7, 732.5, 714.8, 901.7, 788.4, 751.8, 761.4, 821.9, 817.5, 696.7),
  Trial3 = c(734, 748.2, 793.8, 866.1, 713.1, 790.4, 714, 780.6, 876.6, 778)
)

# Dataset 2 (higher consistency)
set2_data <- data.frame(
  Subject = 1:10,
  Trial1 = c(749.6, 702.4, 719.2, 852, 772, 761.6, 744, 837.6, 871.2, 726.4),
  Trial2 = c(802.7, 832.5, 814.8, 951.7, 888.4, 851.8, 861.4, 871.9, 967.5, 846.7),
  Trial3 = c(834, 848.2, 893.8, 966.1, 813.1, 890.4, 814, 880.6, 976.6, 878)
)

# Dataset 3 (greater variability)
set3_data <- data.frame(
  Subject = 1:10,
  Trial1 = c(749.6, 602.4, 719.2, 952, 772, 761.6, 744, 937.6, 971.2, 526.4),
  Trial2 = c(702.7, 632.5, 714.8, 1001.7, 788.4, 751.8, 761.4, 921.9, 917.5, 496.7),
  Trial3 = c(734, 648.2, 793.8, 966.1, 713.1, 790.4, 714, 880.6, 976.6, 578)
)

# Display all three datasets
kable(set1_data, caption = "1 (Original)")%>%
    kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                  full_width = FALSE)
1 (Original)
Subject Trial1 Trial2 Trial3
1 749.6 702.7 734.0
2 702.4 732.5 748.2
3 719.2 714.8 793.8
4 852.0 901.7 866.1
5 772.0 788.4 713.1
6 761.6 751.8 790.4
7 744.0 761.4 714.0
8 837.6 821.9 780.6
9 871.2 817.5 876.6
10 726.4 696.7 778.0
kable(set2_data, caption ="2 (Higher Consistency)")%>%
    kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                  full_width = FALSE)
2 (Higher Consistency)
Subject Trial1 Trial2 Trial3
1 749.6 802.7 834.0
2 702.4 832.5 848.2
3 719.2 814.8 893.8
4 852.0 951.7 966.1
5 772.0 888.4 813.1
6 761.6 851.8 890.4
7 744.0 861.4 814.0
8 837.6 871.9 880.6
9 871.2 967.5 976.6
10 726.4 846.7 878.0
kable(set3_data, caption ="3 (Greater Variability)")%>%
    kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                  full_width = FALSE)
3 (Greater Variability)
Subject Trial1 Trial2 Trial3
1 749.6 702.7 734.0
2 602.4 632.5 648.2
3 719.2 714.8 793.8
4 952.0 1001.7 966.1
5 772.0 788.4 713.1
6 761.6 751.8 790.4
7 744.0 761.4 714.0
8 937.6 921.9 880.6
9 971.2 917.5 976.6
10 526.4 496.7 578.0

Reliability Analysis Function

# Function to analyze reliability for a given dataset
analyze_reliability <- function(data, set_name) {
  cat("## Analysis for Dataset", set_name, "\n\n")
  
  # Calculate averages for each subject
  reliability_data <- data %>%
    rowwise() %>%
    mutate(Average = mean(c(Trial1, Trial2, Trial3)))
  
  # Calculate grand mean
  grand_mean <- mean(c(reliability_data$Trial1, 
                      reliability_data$Trial2, 
                      reliability_data$Trial3))
  
  # Calculate deviations from the grand mean
  reliability_data <- reliability_data %>%
    mutate(
      Deviation_Trial1 = Trial1 - grand_mean,
      Deviation_Trial2 = Trial2 - grand_mean,
      Deviation_Trial3 = Trial3 - grand_mean,
      Avg_Deviation = Average - grand_mean,
      
      DeviationSq_Trial1 = Deviation_Trial1^2,
      DeviationSq_Trial2 = Deviation_Trial2^2,
      DeviationSq_Trial3 = Deviation_Trial3^2,
      Avg_DeviationSq = Avg_Deviation^2,
      
      Trials_Sum_Deviation = DeviationSq_Trial1 + DeviationSq_Trial2 + DeviationSq_Trial3
    )
  
  # Create deviation calculations table (don't print inside function)
  deviation_table <- reliability_data %>%
    select(Subject, Trial1, Trial2, Trial3, Average, 
           Deviation_Trial1, Deviation_Trial2, Deviation_Trial3, Avg_Deviation,
           DeviationSq_Trial1, DeviationSq_Trial2, DeviationSq_Trial3, Avg_DeviationSq,
           Trials_Sum_Deviation)
  
  # Calculate sums of squares
  ss_timepoint <- sum((colMeans(reliability_data[, c("Trial1", "Trial2", "Trial3")]) - grand_mean)^2) * nrow(reliability_data)
  ss_subjects <- sum(reliability_data$Avg_DeviationSq) * 3
  ss_total <- sum(reliability_data$Trials_Sum_Deviation)
  ss_error <- ss_total - ss_timepoint - ss_subjects
  ss_within <- ss_timepoint + ss_error
  
  # Calculate degrees of freedom
  df_timepoint <- 3 - 1
  df_subjects <- nrow(reliability_data) - 1
  df_error <- df_timepoint * df_subjects
  df_total <- (3 * nrow(reliability_data)) - 1
  df_within <- df_timepoint + df_error
  
  # Calculate mean squares
  ms_timepoint <- ss_timepoint / df_timepoint
  ms_subjects <- ss_subjects / df_subjects
  ms_error <- ss_error / df_error
  ms_within <- ss_within / df_within
  
  # Calculate F-statistic
  f_value <- ms_timepoint / ms_error
  
  # Create ANOVA table (don't print inside function)
  anova_table <- data.frame(
    Source = c("Trials", "Between Subject", "Error", "Total", "Within"),
    SS = c(ss_timepoint, ss_subjects, ss_error, ss_total, ss_within),
    DF = c(df_timepoint, df_subjects, df_error, df_total, df_within),
    MS = c(ms_timepoint, ms_subjects, ms_error, NA, ms_within),
    F = c(f_value, ms_subjects/ms_within, NA, NA, NA)
  )
  
  # Calculate ICC (Intraclass Correlation Coefficient)
  icc_value <- (ms_subjects - ms_error) / (ms_subjects + (3-1)*ms_error)
  
  # Calculate standard deviation
  sd_value <- sd(c(reliability_data$Trial1, 
                  reliability_data$Trial2, 
                  reliability_data$Trial3))
  
  # Calculate SEM (Standard Error of Measurement)
  sem_value <- sd_value * sqrt(1 - icc_value)
  
  # Calculate MD (Minimal Difference)
  md_value <- sem_value * 1.96 * sqrt(2)
  
  # Calculate the Coefficient of Variation (CoV)
  cov_value <- (sd_value / grand_mean) * 100
  
  # Create reliability metrics table (don't print inside function)
  reliability_metrics <- data.frame(
    Metric = c("ICC", "SD", "SEM", "MD", "CoV (%)"),
    Value = c(icc_value, sd_value, sem_value, md_value, cov_value)
  )
  
  # Create visualization of the trials data
  reliability_data_long <- reliability_data %>%
    select(Subject, Trial1, Trial2, Trial3) %>%
    pivot_longer(cols = c(Trial1, Trial2, Trial3),
                 names_to = "Trial",
                 values_to = "Value")
  
  # Create plot (don't print inside function)
  p <- ggplot(reliability_data_long, aes(x = Trial, y = Value, group = Subject, color = factor(Subject))) +
    geom_line() +
    geom_point(size = 3) +
    theme_pubr() +
    scale_color_npg() +
    labs(
      title = paste("Reliability of Measurements in Dataset", set_name),
      subtitle = paste("ICC =", round(icc_value, 3)),
      x = "Trial",
      y = "Measurement Value",
      color = "Subject"
    )
  
  # Return all results as a list
  return(list(
    dataset = set_name,
    grand_mean = grand_mean,
    icc = icc_value,
    sd = sd_value,
    sem = sem_value,
    md = md_value,
    cov = cov_value,
    deviation_table = deviation_table,
    anova_table = anova_table,
    reliability_metrics = reliability_metrics,
    plot = p
  ))
}

Analysis of Each Dataset

# Analyze all three datasets and store complete results
results1 <- analyze_reliability(set1_data, "1 (Original)")
## ## Analysis for Dataset 1 (Original)
results2 <- analyze_reliability(set2_data, "2 (Higher Consistency)")
## ## Analysis for Dataset 2 (Higher Consistency)
results3 <- analyze_reliability(set3_data, "3 (Greater Variability)")
## ## Analysis for Dataset 3 (Greater Variability)
# Now display the tables and plots for each dataset with proper formatting
# Dataset 1
cat("### Deviation Calculations\n\n")
## ### Deviation Calculations
results1$deviation_table %>%
  kable(digits = 2) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Subject Trial1 Trial2 Trial3 Average Deviation_Trial1 Deviation_Trial2 Deviation_Trial3 Avg_Deviation DeviationSq_Trial1 DeviationSq_Trial2 DeviationSq_Trial3 Avg_DeviationSq Trials_Sum_Deviation
1 749.6 702.7 734.0 728.77 -24.41 -71.31 -40.01 -45.24 595.69 5084.64 1600.53 2046.66 7280.86
2 702.4 732.5 748.2 727.70 -71.61 -41.51 -25.81 -46.31 5127.51 1722.80 665.98 2144.31 7516.30
3 719.2 714.8 793.8 742.60 -54.81 -59.21 19.79 -31.41 3003.77 3505.43 391.78 986.38 6900.98
4 852.0 901.7 866.1 873.27 77.99 127.69 92.09 99.26 6082.96 16305.59 8481.18 9852.55 30869.73
5 772.0 788.4 713.1 757.83 -2.01 14.39 -60.91 -16.17 4.03 207.17 3709.62 261.58 3920.82
6 761.6 751.8 790.4 767.93 -12.41 -22.21 16.39 -6.07 153.93 493.14 268.74 36.89 915.80
7 744.0 761.4 714.0 739.80 -30.01 -12.61 -60.01 -34.21 900.40 158.93 3600.80 1170.10 4660.13
8 837.6 821.9 780.6 813.37 63.59 47.89 6.59 39.36 4044.11 2293.77 43.47 1549.21 6381.36
9 871.2 817.5 876.6 855.10 97.19 43.49 102.59 81.09 9446.54 1891.67 10525.39 6576.13 21863.61
10 726.4 696.7 778.0 733.70 -47.61 -77.31 3.99 -40.31 2266.39 5976.32 15.95 1624.63 8258.66
cat("\n\n")
cat("### Repeated Measures ANOVA Table\n\n")
## ### Repeated Measures ANOVA Table
results1$anova_table %>%
  kable(digits = 2) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Source SS DF MS F
Trials 557.94 2 278.97 0.26
Between Subject 78745.25 9 8749.47 8.83
Error 19265.05 18 1070.28 NA
Total 98568.24 29 NA NA
Within 19822.99 20 991.15 NA
cat("\n\n")
cat("### Reliability Metrics\n\n")
## ### Reliability Metrics
results1$reliability_metrics %>%
  kable(digits = 3) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Metric Value
ICC 0.705
SD 58.300
SEM 31.657
MD 87.748
CoV (%) 7.532
cat("\n\n")
cat("### Visualization\n\n")
## ### Visualization
print(results1$plot)

# Dataset 2
cat("\n\n")
cat("### Deviation Calculations\n\n")
## ### Deviation Calculations
results2$deviation_table %>%
  kable(digits = 2) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Subject Trial1 Trial2 Trial3 Average Deviation_Trial1 Deviation_Trial2 Deviation_Trial3 Avg_Deviation DeviationSq_Trial1 DeviationSq_Trial2 DeviationSq_Trial3 Avg_DeviationSq Trials_Sum_Deviation
1 749.6 802.7 834.0 795.43 -91.07 -37.97 -6.67 -45.24 8294.35 1441.97 44.53 2046.66 9780.86
2 702.4 832.5 848.2 794.37 -138.27 -8.17 7.53 -46.31 19119.51 66.80 56.65 2144.31 19242.97
3 719.2 814.8 893.8 809.27 -121.47 -25.87 53.13 -31.41 14755.77 669.43 2822.44 986.38 18247.64
4 852.0 951.7 966.1 923.27 11.33 111.03 125.43 82.59 128.29 12326.92 15731.85 6821.66 28187.06
5 772.0 888.4 813.1 824.50 -68.67 47.73 -27.57 -16.17 4716.03 2277.83 760.29 261.58 7754.15
6 761.6 851.8 890.4 834.60 -79.07 11.13 49.73 -6.07 6252.59 123.80 2472.74 36.89 8849.14
7 744.0 861.4 814.0 806.47 -96.67 20.73 -26.67 -34.21 9345.73 429.59 711.47 1170.10 10486.79
8 837.6 871.9 880.6 863.37 -3.07 31.23 39.93 22.69 9.45 975.10 1594.14 514.99 2578.69
9 871.2 967.5 976.6 938.43 30.53 126.83 135.93 97.76 931.88 16085.00 18476.06 9557.02 35492.94
10 726.4 846.7 878.0 817.03 -114.27 6.03 37.33 -23.64 13058.39 36.32 1393.28 558.85 14488.00
cat("\n\n")
cat("### Repeated Measures ANOVA Table\n\n")
## ### Repeated Measures ANOVA Table
results2$anova_table %>%
  kable(digits = 2) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Source SS DF MS F
Trials 68037.94 2 34018.97 41.44
Between Subject 72295.25 9 8032.81 1.94
Error 14775.05 18 820.84 NA
Total 155108.24 29 NA NA
Within 82812.99 20 4140.65 NA
cat("\n\n")
cat("### Reliability Metrics\n\n")
## ### Reliability Metrics
results2$reliability_metrics %>%
  kable(digits = 3) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Metric Value
ICC 0.745
SD 73.134
SEM 36.897
MD 102.274
CoV (%) 8.699
cat("\n\n")
cat("### Visualization\n\n")
## ### Visualization
print(results2$plot)

# Dataset 3
cat("\n\n")
cat("### Deviation Calculations\n\n")
## ### Deviation Calculations
results3$deviation_table %>%
  kable(digits = 2) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Subject Trial1 Trial2 Trial3 Average Deviation_Trial1 Deviation_Trial2 Deviation_Trial3 Avg_Deviation DeviationSq_Trial1 DeviationSq_Trial2 DeviationSq_Trial3 Avg_DeviationSq Trials_Sum_Deviation
1 749.6 702.7 734.0 728.77 -24.41 -71.31 -40.01 -45.24 595.69 5084.64 1600.53 2046.66 7280.86
2 602.4 632.5 648.2 627.70 -171.61 -141.51 -125.81 -146.31 29448.85 20024.14 15827.32 21405.64 65300.30
3 719.2 714.8 793.8 742.60 -54.81 -59.21 19.79 -31.41 3003.77 3505.43 391.78 986.38 6900.98
4 952.0 1001.7 966.1 973.27 177.99 227.69 192.09 199.26 31681.63 51844.25 36899.85 39704.55 120425.73
5 772.0 788.4 713.1 757.83 -2.01 14.39 -60.91 -16.17 4.03 207.17 3709.62 261.58 3920.82
6 761.6 751.8 790.4 767.93 -12.41 -22.21 16.39 -6.07 153.93 493.14 268.74 36.89 915.80
7 744.0 761.4 714.0 739.80 -30.01 -12.61 -60.01 -34.21 900.40 158.93 3600.80 1170.10 4660.13
8 937.6 921.9 880.6 913.37 163.59 147.89 106.59 139.36 26762.78 21872.44 11362.14 19421.21 59997.36
9 971.2 917.5 976.6 955.10 197.19 143.49 202.59 181.09 38885.21 20590.34 41044.06 32794.80 100519.61
10 526.4 496.7 578.0 533.70 -247.61 -277.31 -196.01 -240.31 61309.06 76898.99 38418.61 57747.29 176626.66
cat("\n\n")
cat("### Repeated Measures ANOVA Table\n\n")
## ### Repeated Measures ANOVA Table
results3$anova_table %>%
  kable(digits = 2) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Source SS DF MS F
Trials 557.94 2 278.97 0.26
Between Subject 526725.25 9 58525.03 59.05
Error 19265.05 18 1070.28 NA
Total 546548.24 29 NA NA
Within 19822.99 20 991.15 NA
cat("\n\n")
cat("### Reliability Metrics\n\n")
## ### Reliability Metrics
results3$reliability_metrics %>%
  kable(digits = 3) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Metric Value
ICC 0.947
SD 137.283
SEM 31.583
MD 87.544
CoV (%) 17.737
cat("\n\n")
cat("### Visualization\n\n")
## ### Visualization
print(results3$plot)

Comparison of Results

# Create comparison table
comparison_table <- data.frame(
  Dataset = c(results1$dataset, results2$dataset, results3$dataset),
  Grand_Mean = c(results1$grand_mean, results2$grand_mean, results3$grand_mean),
  ICC = c(results1$icc, results2$icc, results3$icc),
  SD = c(results1$sd, results2$sd, results3$sd),
  SEM = c(results1$sem, results2$sem, results3$sem),
  MD = c(results1$md, results2$md, results3$md),
  CoV_percent = c(results1$cov, results2$cov, results3$cov)
)

# Display comparison table
comparison_table %>%
  kable(digits = 3, 
        col.names = c("Dataset", "Grand Mean", "ICC", "SD", "SEM", "MD", "CoV (%)")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Dataset Grand Mean ICC SD SEM MD CoV (%)
1 (Original) 774.007 0.705 58.300 31.657 87.748 7.532
2 (Higher Consistency) 840.673 0.745 73.134 36.897 102.274 8.699
3 (Greater Variability) 774.007 0.947 137.283 31.583 87.544 17.737
# Create bar plot for ICC comparison
icc_comparison <- data.frame(
  Dataset = c(results1$dataset, results2$dataset, results3$dataset),
  ICC = c(results1$icc, results2$icc, results3$icc)
)

ggplot(icc_comparison, aes(x = Dataset, y = ICC, fill = Dataset)) +
  geom_bar(stat = "identity") +
  theme_pubr() +
  scale_fill_npg() +
  labs(
    title = "Comparison of ICC Values Across Datasets",
    subtitle = "Impact of Data Variability on Reliability",
    x = "Dataset",
    y = "Intraclass Correlation Coefficient (ICC)"
  ) +
  theme(legend.position = "none")

# Create bar plot for SEM and MD comparison
sem_md_comparison <- data.frame(
  Dataset = rep(c(results1$dataset, results2$dataset, results3$dataset), 2),
  Metric = c(rep("SEM", 3), rep("MD", 3)),
  Value = c(results1$sem, results2$sem, results3$sem, 
            results1$md, results2$md, results3$md)
)

ggplot(sem_md_comparison, aes(x = Dataset, y = Value, fill = Metric)) +
  geom_bar(stat = "identity", position = "dodge") +
  theme_pubr() +
  scale_fill_npg() +
  labs(
    title = "Comparison of SEM and MD Values Across Datasets",
    subtitle = "Impact of Data Variability on Measurement Error",
    x = "Dataset",
    y = "Value"
  )

Discussion and Interpretation

The analysis of the three datasets with varying levels of data consistency demonstrates how reliability metrics are affected by changes in data variability:

  1. Dataset 1 (Original): This dataset serves as our baseline with moderate reliability.

  2. Dataset 2 (Higher Consistency): This dataset shows higher consistency between trials for each subject. As a result:

    • The ICC value increased, indicating improved reliability
    • The SEM decreased, showing better precision of measurements
    • The MD decreased, meaning smaller changes can be detected reliably
  3. Dataset 3 (Greater Variability): This dataset demonstrates increased variability between both subjects and trials. As a result:

    • The ICC value decreased substantially, indicating poorer reliability
    • The SEM increased, showing reduced precision of measurements
    • The MD increased, meaning larger changes are needed to detect real differences

These comparisons illustrate the sensitivity of reliability metrics to data variability. When designing measurement protocols, researchers should strive for conditions that minimize variability to achieve higher reliability, lower SEM, and smaller MD values, which allow for more precise detection of true changes in the measured variable.

Conclusions for Investigators

When reporting reliability metrics to principal investigators, the following considerations are important:

  1. ICC Interpretation:

    • ICC > 0.90: Excellent reliability
    • ICC 0.75-0.90: Good reliability
    • ICC 0.50-0.75: Moderate reliability
    • ICC < 0.50: Poor reliability
  2. SEM and MD: These metrics provide practical information about the precision of measurements and the ability to detect real changes. A lower SEM and MD indicate greater measurement precision.

  3. Coefficient of Variation: The CoV provides a standardized measure of dispersion that allows comparison across different measurement scales. Lower CoV values indicate less variability relative to the mean.

When evaluating a measurement protocol, investigators should consider both the statistical reliability (ICC) and the practical implications of measurement error (SEM, MD) for their specific research questions and populations of interest.


Executive Summary

This analysis examines the impact of training on bench press performance over time. Using a dataset that tracks bench press weights for trained and untrained subjects across three time points (PRE, MID, and POST), we performed several statistical analyses to assess differences between groups and changes over time. One-way ANOVA revealed significant differences in baseline strength between trained and untrained subjects. Repeated measures ANOVA demonstrated significant improvements in bench press performance over time for all subjects, with trained subjects showing greater overall strength values. A factorial ANOVA confirmed both main effects of training status and time, as well as their interaction, indicating that trained subjects experienced different rates of strength improvement compared to untrained subjects.


MRP DATA ANOVA, rmANOVA, Factorial

Introduction

Background and Rationale

Resistance training is a fundamental component of athletic development and general fitness. Understanding the differences in strength development between trained and untrained individuals provides valuable insights for program design and expected adaptations. This analysis uses the bench press exercise as a model to examine these differences. The bench press is one of the most common and well-studied resistance exercises, making it an ideal choice for demonstrating statistical analysis techniques in exercise science.

Objectives and Hypotheses

Objectives: - To compare baseline strength levels between trained and untrained individuals - To assess changes in bench press performance over time (PRE, MID, POST) - To determine if training status affects the rate of strength development

Hypotheses: 1. Trained individuals will demonstrate greater baseline (PRE) bench press strength than untrained individuals 2. All subjects will show significant increases in bench press performance over time 3. Trained individuals will exhibit different patterns of strength development compared to untrained individuals (interaction effect)

Methods

Experimental Design

This study employed a mixed factorial design with one between-subjects factor (Training Status: Trained vs. Untrained) and one within-subjects factor (Time: PRE, MID, POST). The dependent variable was bench press performance measured in kilograms (kg). This design allows us to examine both between-group differences and within-subject changes over time.

Subjects

Participants (n=9, 6M/3F, mean±SD: 31±6y, 174±12cm, 82±25kg) completed the 12-week intervention. They were categorized as trained (V̇O2max >35 mlkg−1min−1, n=4) or untrained (n=5) based on baseline cardiorespiratory fitness. Participants had not engaged in structured resistance training for at least 1 year prior to the study.

Procedures

Testing sessions occurred at baseline (PRE), 6 weeks (MID), and 12 weeks (POST). Bench press performance was assessed using the one-repetition maximum (1RM) test following National Strength and Conditioning Association standards. Briefly, subjects warmed up with 8-10 repetitions at 50% estimated 1RM, followed by 3-5 repetitions at 85% estimated 1RM. Subjects then performed 2-4 maximal testing attempts with 3-5 minutes of rest between attempts.

Exercise Intervention

Participants completed a 12-week minimal-dose exercise intervention consisting of once-weekly, one-hour sessions that combined high-intensity interval training (HIIT), resistance training (RT), and high-intensity functional training (HIFT). For resistance exercises (including bench press), participants performed a single set of 25-30 repetitions to failure at 64±16% 1RM. The training load was adjusted based on performance, with increases implemented if participants completed more than 30 repetitions and decreases if they completed fewer than 25 repetitions.

Statistical Analysis

All analyses were conducted in R version 4.4.1 using RStudio version 2024.12.1+563. Data manipulation was performed with the tidyverse suite of packages including dplyr for data transformation and tidyr for reshaping. Normality and homogeneity were confirmed with the Shapiro-Wilk and Levene’s test using the car package.

To address our research questions, the following analyses were conducted:

  1. One-way ANOVA: To examine differences in baseline (PRE) bench press strength between trained and untrained individuals. When significant main effects were detected, post-hoc comparisons were conducted using Tukey’s Honestly Significant Difference (HSD) test to identify which specific group means differed significantly while controlling for family-wise error rate. The tukey_hsd function from the rstatix package was used for these comparisons.

  2. Repeated Measures ANOVA: To assess changes in bench press performance over time (PRE, MID, POST) across all subjects. Mauchly’s test was used to check the sphericity assumption, with Greenhouse-Geisser correction applied when necessary. Following significant time effects, post-hoc pairwise comparisons between all time points (PRE vs. MID, MID vs. POST, and PRE vs. POST) were conducted using paired t-tests with Bonferroni correction (p.adjust.method = “bonferroni”) to control for multiple comparisons. These analyses were implemented using the pairwise_t_test function from the rstatix package.

  3. Group-Specific Repeated Measures ANOVA: To analyze changes over time separately for each training status group, identifying group-specific patterns of adaptation. For each significant time effect within groups, post-hoc pairwise comparisons were conducted using paired t-tests with Bonferroni correction to determine which specific time points showed significant differences. Within each training group, effect sizes were calculated using generalized eta squared (ges) to quantify the magnitude of the time effect.

  4. Mixed Factorial ANOVA: To examine both main effects (Training Status and Time) and their interaction. This analysis allows us to determine whether training status influences the rate of strength development over time. When significant interaction effects were found, simple effects analyses were conducted to examine differences between groups at each time point. For simple effects of Training Status at each level of Time, one-way ANOVAs were performed followed by Tukey’s HSD post-hoc tests to identify group differences. For simple effects of Time at each level of Training Status, repeated measures ANOVAs were conducted followed by Bonferroni-corrected pairwise comparisons.

For all analyses, statistical significance was set at p < 0.05. Effect sizes were quantified using partial eta squared (η²p) for ANOVA effects and Hedges’ g with bias correction for small samples for pairwise comparisons. Data normality was visually inspected using histograms created with ggplot2, and data visualization was performed using the ggpubr package to create publication-quality figures following Nature style guidelines.

# Load the conflicted package
library(conflicted)

# Resolve conflicts in favor of dplyr for common functions
conflict_prefer("filter", "dplyr")
conflict_prefer("select", "dplyr")
conflict_prefer("group_by", "dplyr")
conflict_prefer("mutate", "dplyr")
conflict_prefer("summarize", "dplyr")
conflict_prefer("summarise", "dplyr")
conflict_prefer("rename", "dplyr")
conflict_prefer("arrange", "dplyr")

# If you're experiencing conflicts with specific functions, add them here
# For example, conflict with stats package:
conflict_prefer("filter", "dplyr", quiet = TRUE)
conflict_prefer("lag", "dplyr", quiet = TRUE)
# Load the dataset
data <- read_excel("G:/My Drive/UCONN/UHart/04152025 ANOVA and reliability.xlsx",
                   sheet = "ANOVA", range = "A1:I22") %>%
        select(-c(4, 5, 6))  # Exclude columns D, E, F (4th to 6th)

# Display first few rows of the dataset
head(data) %>%
  kable() %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Subject Training Status Exercise PRE (kg) MID (kg) POST (kg)
SUB 3 Trained 1RM Bench Press 86.18 92.99 92.99
SUB 66 Trained 1RM Bench Press 80.35 86.70 90.10
SUB 18 Trained 1RM Bench Press 77.11 81.65 88.45
SUB 13 Trained 1RM Bench Press 72.57 79.38 83.91
SUB 5 Trained 1RM Bench Press 70.31 74.84 81.65
SUB 15 Trained 1RM Bench Press 68.04 74.84 79.38
# Data structure overview
str(data)
## tibble [21 × 6] (S3: tbl_df/tbl/data.frame)
##  $ Subject        : chr [1:21] "SUB 3" "SUB 66" "SUB 18" "SUB 13" ...
##  $ Training Status: chr [1:21] "Trained" "Trained" "Trained" "Trained" ...
##  $ Exercise       : chr [1:21] "1RM Bench Press" "1RM Bench Press" "1RM Bench Press" "1RM Bench Press" ...
##  $ PRE (kg)       : num [1:21] 86.2 80.3 77.1 72.6 70.3 ...
##  $ MID (kg)       : num [1:21] 93 86.7 81.7 79.4 74.8 ...
##  $ POST (kg)      : num [1:21] 93 90.1 88.5 83.9 81.7 ...
# Summary statistics of numerical variables
summary(data) %>%
  kable() %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Subject Training Status Exercise PRE (kg) MID (kg) POST (kg)
Length:21 Length:21 Length:21 Min. :47.63 Min. :52.16 Min. :54.43
Class :character Class :character Class :character 1st Qu.:56.70 1st Qu.:63.50 1st Qu.:69.40
Mode :character Mode :character Mode :character Median :62.60 Median :68.95 Median :74.84
NA NA NA Mean :63.35 Mean :69.55 Mean :74.62
NA NA NA 3rd Qu.:68.04 3rd Qu.:74.84 3rd Qu.:79.38
NA NA NA Max. :86.18 Max. :92.99 Max. :92.99

Data Preprocessing

# Clean column names (removing spaces and special characters)
names(data) <- c("Subject", "TrainingStatus", "Exercise", "PRE", "MID", "POST")

# Convert Training Status to a factor with correct levels
data$TrainingStatus <- factor(data$TrainingStatus, levels = c("Trained", "Recreational", "Untrained"))

# Check for missing values
missing_values <- colSums(is.na(data))
print(missing_values)
##        Subject TrainingStatus       Exercise            PRE            MID 
##              0              0              0              0              0 
##           POST 
##              0
# Create a long format dataset for repeated measures analyses
data_long <- data %>%
  pivot_longer(
    cols = c(PRE, MID, POST),
    names_to = "TimePoint",
    values_to = "Weight"
  ) %>%
  mutate(TimePoint = factor(TimePoint, levels = c("PRE", "MID", "POST")))

# Display first few rows of the long format data
head(data_long) %>%
  kable() %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Subject TrainingStatus Exercise TimePoint Weight
SUB 3 Trained 1RM Bench Press PRE 86.18
SUB 3 Trained 1RM Bench Press MID 92.99
SUB 3 Trained 1RM Bench Press POST 92.99
SUB 66 Trained 1RM Bench Press PRE 80.35
SUB 66 Trained 1RM Bench Press MID 86.70
SUB 66 Trained 1RM Bench Press POST 90.10

Descriptive Statistics

# Descriptive statistics by training status for PRE values
pre_stats <- data %>%
  group_by(TrainingStatus) %>%
  summarize(
    n = n(),
    Mean = mean(PRE),
    SD = sd(PRE),
    Min = min(PRE),
    Max = max(PRE),
    SE = SD / sqrt(n)
  )

# Display the descriptive statistics
pre_stats %>%
  kable(caption = "Descriptive Statistics for PRE Bench Press Values by Training Status") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Descriptive Statistics for PRE Bench Press Values by Training Status
TrainingStatus n Mean SD Min Max SE
Trained 7 74.52714 7.009296 67.13 86.18 2.6492647
Recreational 7 62.46571 2.451087 58.97 65.77 0.9264239
Untrained 7 53.07143 4.098908 47.63 57.61 1.5492416
# Descriptive statistics by training status and time point
time_stats <- data_long %>%
  group_by(TrainingStatus, TimePoint) %>%
  summarize(
    n = n(),
    Mean = mean(Weight),
    SD = sd(Weight),
    Min = min(Weight),
    Max = max(Weight),
    SE = SD / sqrt(n),
    .groups = "drop"  # This avoids the grouping message
  )

# Display the descriptive statistics
time_stats %>%
  kable(caption = "Descriptive Statistics for Bench Press Values by Training Status and Time Point") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Descriptive Statistics for Bench Press Values by Training Status and Time Point
TrainingStatus TimePoint n Mean SD Min Max SE
Trained PRE 7 74.52714 7.009296 67.13 86.18 2.6492647
Trained MID 7 80.36000 7.429394 72.12 92.99 2.8080471
Trained POST 7 84.08571 7.138984 72.12 92.99 2.6982824
Recreational PRE 7 62.46571 2.451087 58.97 65.77 0.9264239
Recreational MID 7 68.81714 2.829568 63.50 72.57 1.0694763
Recreational POST 7 75.10143 4.073002 68.04 79.38 1.5394502
Untrained PRE 7 53.07143 4.098908 47.63 57.61 1.5492416
Untrained MID 7 59.48429 5.415197 52.16 65.77 2.0467522
Untrained POST 7 64.67000 6.542051 54.43 70.31 2.4726629

Data Visualization

# 1. Boxplot of PRE values by training status
p1 <- ggboxplot(
  data, x = "TrainingStatus", y = "PRE",
  color = "TrainingStatus", palette = "npg",
  add = "jitter", shape = "TrainingStatus"
) +
  stat_compare_means(method = "anova", label = "p.signif") +  # Changed to ANOVA for 3 groups
  theme_pubr(base_size = 12) +
  labs(
    title = "Baseline Bench Press Performance by Training Status",
    x = "Training Status",
    y = "Bench Press 1RM (kg)"
  )

# 2. Line plot showing changes over time by training status
p2 <- ggline(
  data_long, x = "TimePoint", y = "Weight",
  color = "TrainingStatus", palette = "npg",
  add = "mean_se", point.size = 3, line.size = 1
) +
  theme_pubr(base_size = 12) +
  labs(
    title = "Bench Press Performance Over Time by Training Status",
    x = "Time Point",
    y = "Bench Press 1RM (kg)"
  )

# 3. Bar plot showing PRE, MID, POST by training status
p3 <- ggbarplot(
  data_long, x = "TimePoint", y = "Weight",
  fill = "TrainingStatus", palette = "npg",
  position = position_dodge(0.8),
  add = "mean_se"
) +
  theme_pubr(base_size = 12) +
  labs(
    title = "Bench Press Performance by Time Point and Training Status",
    x = "Time Point",
    y = "Bench Press 1RM (kg)"
  )

# Display plots
print(p1)

print(p2)

print(p3)

# 4. Individual trajectories
p4 <- ggplot(data_long, aes(x = TimePoint, y = Weight, group = Subject, color = TrainingStatus)) +
  geom_line(alpha = 0.7) +
  geom_point(size = 2) +
  scale_color_npg() +
  theme_pubr(base_size = 12) +
  labs(
    title = "Individual Bench Press Trajectories by Training Status",
    x = "Time Point",
    y = "Bench Press 1RM (kg)"
  )

print(p4)

Statistical Analysis

1. One-way ANOVA on PRE values by Training Status

First, we’ll examine if there are significant differences in baseline (PRE) bench press performance between training status groups.

# Check assumptions for one-way ANOVA
# Normality test for PRE values by group
shapiro_test_results <- data %>%
  group_by(TrainingStatus) %>%
  shapiro_test(PRE)

shapiro_test_results %>%
  kable(caption = "Shapiro-Wilk Normality Test for PRE Values") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Shapiro-Wilk Normality Test for PRE Values
TrainingStatus variable statistic p
Trained PRE 0.9302983 0.5534394
Recreational PRE 0.9755850 0.9354945
Untrained PRE 0.8794798 0.2241491
# Homogeneity of variance test
levene_test_result <- data %>%
  levene_test(PRE ~ TrainingStatus)

levene_test_result %>%
  kable(caption = "Levene's Test for Homogeneity of Variances") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Levene’s Test for Homogeneity of Variances
df1 df2 statistic p
2 18 2.398263 0.1192984
# One-way ANOVA
anova_result <- data %>%
  anova_test(PRE ~ TrainingStatus)

anova_result %>%
  kable(caption = "One-way ANOVA Results for PRE Values by Training Status") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
One-way ANOVA Results for PRE Values by Training Status
Effect DFn DFd F p p<.05 ges
TrainingStatus 2 18 33.768 8e-07
0.79
# Calculate effect size (eta squared)
eta_squared <- anova_result$ges

cat("Effect size (eta squared):", eta_squared, "\n")
## Effect size (eta squared): 0.79
# Post-hoc tests for one-way ANOVA (since we now have 3 groups)
posthoc_tukey <- data %>% 
  tukey_hsd(PRE ~ TrainingStatus)

posthoc_tukey %>%
  kable(caption = "Tukey's HSD Post-hoc Tests for Training Status") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Tukey’s HSD Post-hoc Tests for Training Status
term group1 group2 null.value estimate conf.low conf.high p.adj p.adj.signif
TrainingStatus Trained Recreational 0 -12.061429 -18.74173 -5.381124 6.09e-04 ***
TrainingStatus Trained Untrained 0 -21.455714 -28.13602 -14.775409 5.00e-07 ****
TrainingStatus Recreational Untrained 0 -9.394286 -16.07459 -2.713981 5.66e-03 **

2. Repeated Measures ANOVA (Overall)

Next, we’ll analyze changes in bench press performance over time for all subjects using repeated measures ANOVA.

# Check assumptions for repeated measures ANOVA
# Normality of residuals
model <- lm(Weight ~ TimePoint, data = data_long)
residuals <- residuals(model)
rstatix::shapiro_test(residuals) %>%
  kable(caption = "Shapiro-Wilk Test for Normality of Residuals") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Shapiro-Wilk Test for Normality of Residuals
variable statistic p.value
residuals 0.9821107 0.4903513
# Sphericity assumption will be checked when running the analysis

# Handle potential namespace issues with explicit package references
rm_anova_result <- data_long %>%
  dplyr::group_by(data_long$Subject) %>%  # Explicitly use dplyr's group_by
  rstatix::anova_test(dv = Weight, wid = Subject, within = TimePoint) %>%
  rstatix::get_anova_table()

rm_anova_result %>%
  kable(caption = "Repeated Measures ANOVA Results for Changes Over Time") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Repeated Measures ANOVA Results for Changes Over Time
data_long$Subject Effect DFn DFd F p p<.05 ges
SUB 1 TimePoint 2 0 NaN NaN NA 1
SUB 10 TimePoint 2 0 NaN NaN NA 1
SUB 11 TimePoint 2 0 NaN NaN NA 1
SUB 12 TimePoint 2 0 NaN NaN NA 1
SUB 13 TimePoint 2 0 NaN NaN NA 1
SUB 14 TimePoint 2 0 NaN NaN NA 1
SUB 15 TimePoint 2 0 NaN NaN NA 1
SUB 16 TimePoint 2 0 NaN NaN NA 1
SUB 17 TimePoint 2 0 NaN NaN NA 1
SUB 18 TimePoint 2 0 NaN NaN NA 1
SUB 19 TimePoint 2 0 NaN NaN NA 1
SUB 2 TimePoint 2 0 NaN NaN NA 1
SUB 20 TimePoint 2 0 NaN NaN NA 1
SUB 3 TimePoint 2 0 NaN NaN NA 1
SUB 4 TimePoint 2 0 NaN NaN NA 1
SUB 5 TimePoint 2 0 NaN NaN NA 1
SUB 6 TimePoint 2 0 NaN NaN NA 1
SUB 66 TimePoint 2 0 NaN NaN NA 1
SUB 7 TimePoint 2 0 NaN NaN NA 1
SUB 8 TimePoint 2 0 NaN NaN NA 1
SUB 9 TimePoint 2 0 NaN NaN NA 1
# Post-hoc pairwise comparisons with Bonferroni correction
pairwise_result <- data_long %>%
  rstatix::pairwise_t_test(
    Weight ~ TimePoint, paired = TRUE,
    p.adjust.method = "bonferroni"
  )

pairwise_result %>%
  kable(caption = "Post-hoc Pairwise Comparisons Between Time Points") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Post-hoc Pairwise Comparisons Between Time Points
.y. group1 group2 n1 n2 statistic df p p.adj p.adj.signif
Weight PRE MID 21 21 -16.481492 20 0 0 ****
Weight PRE POST 21 21 -16.409486 20 0 0 ****
Weight MID POST 21 21 -9.880306 20 0 0 ****

3. Repeated Measures ANOVA by Group

Now, we’ll analyze changes over time separately for each training status group.

# For each training status group
training_groups <- unique(data$TrainingStatus)
# Empty lists to store ANOVA results
group_rm_anova_results <- list()

# First perform all analyses and store results
for(group in training_groups) {
  # Filter data for current group
  group_data <- data_long %>%
    dplyr::filter(TrainingStatus == group)
  
  # Run the repeated measures ANOVA
  group_rm_anova <- rstatix::anova_test(
    data = group_data,
    dv = Weight, 
    wid = Subject,
    within = TimePoint
  ) %>%
    rstatix::get_anova_table()
  
  # Store ANOVA results
  group_rm_anova_results[[group]] <- group_rm_anova
}

# Create a combined table of all ANOVA results
combined_anova_results <- data.frame(
  TrainingGroup = character(),
  Effect = character(),
  DFn = numeric(),
  DFd = numeric(),
  F = numeric(),
  p = numeric(),
  ges = numeric(),
  stringsAsFactors = FALSE
)

# Loop through each training group to collect results
for(group in training_groups) {
  # Extract the data manually from each group result
  temp_df <- data.frame(
    TrainingGroup = group,
    Effect = group_rm_anova_results[[group]]$Effect,
    DFn = group_rm_anova_results[[group]]$DFn,
    DFd = group_rm_anova_results[[group]]$DFd,
    F = group_rm_anova_results[[group]]$F,
    p = group_rm_anova_results[[group]]$p,
    ges = group_rm_anova_results[[group]]$ges,
    stringsAsFactors = FALSE
  )
  
  # Combine with the main results dataframe
  combined_anova_results <- rbind(combined_anova_results, temp_df)
}

# Display the combined table with proper formatting
knitr::kable(combined_anova_results, 
             caption = "Repeated Measures ANOVA Results by Training Group",
             digits = 3,
             format = "markdown") %>%
  kableExtra::kable_styling(bootstrap_options = c("striped", "hover"), 
                full_width = FALSE)
Repeated Measures ANOVA Results by Training Group
TrainingGroup Effect DFn DFd F p ges
Trained TimePoint 2.00 12.00 60.620 0 0.259
Recreational TimePoint 2.00 12.00 72.548 0 0.753
Untrained TimePoint 1.18 7.06 115.314 0 0.470
# Create a faceted plot with significance annotations
anova_plot <- ggpubr::ggboxplot(
  data_long, 
  x = "TimePoint", 
  y = "Weight",
  fill = "TimePoint",
  facet.by = "TrainingStatus",
  palette = "npg",  # Nature Publishing Group palette
  add = "jitter",   # Add individual data points
  add.params = list(alpha = 0.5, size = 2)
) +
  # Add significance comparisons
  ggpubr::stat_compare_means(
    comparisons = list(
      c("PRE", "MID"), 
      c("MID", "POST"),
      c("PRE", "POST")
    ),
    method = "t.test", 
    paired = TRUE,
    label = "p.value"  # Shows significance stars
  ) +
  # Add Nature-style theme elements
  theme_pubr(base_size = 12) +
  labs(
    title = "Weight Changes Across Training Period",
    subtitle = "Exercise: 1RM Bench Press",
    x = "Time Point",
    y = "Weight (kg)"
  ) +
  theme(
    legend.position = "none",
    strip.background = element_rect(fill = "white", color = "black"),
    strip.text = element_text(face = "bold", size = 12),
    axis.title = element_text(size = 12, face = "bold"),
    axis.text = element_text(size = 10),
    plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
    plot.subtitle = element_text(hjust = 0.5, size = 12)
  )

# Print the plot
print(anova_plot)

4. Factorial ANOVA (Mixed Design ANOVA)

Finally, we’ll conduct a factorial ANOVA to examine both main effects and the interaction between Training Status and Time.

# Mixed ANOVA with one between-subjects factor (TrainingStatus) 
# and one within-subjects factor (TimePoint)

# Calculate the mixed ANOVA and store results
mixed_anova_result <- rstatix::anova_test(
  data = data_long,
  dv = Weight, 
  wid = Subject, 
  between = TrainingStatus, 
  within = TimePoint
) %>%
  rstatix::get_anova_table()

# Calculate effect sizes (partial eta squared)
mixed_anova_result$pes <- mixed_anova_result$ges / (1 - mixed_anova_result$ges)

# Create effect sizes table using a manual approach
effect_sizes_table <- data.frame(
  Effect = mixed_anova_result$Effect,
  p = mixed_anova_result$p,
  ges = mixed_anova_result$ges,
  pes = mixed_anova_result$pes
)
# Simple effect of Training Status at each level of Time
simple_effects_time <- data_long %>%
  dplyr::group_by(TimePoint) %>%
  rstatix::anova_test(Weight ~ TrainingStatus) %>%
  rstatix::get_anova_table()

# Create list to store post-hoc test results
posthoc_by_timepoint <- list()

# Perform post-hoc tests for each time point and store results
for(time_point in c("PRE", "MID", "POST")) {
  time_data <- data_long %>% dplyr::filter(TimePoint == time_point)
  
  posthoc_result <- time_data %>%
    rstatix::tukey_hsd(Weight ~ TrainingStatus)
  
  posthoc_by_timepoint[[time_point]] <- posthoc_result
}

# Calculate mean values for each group at each time point
mean_by_group_time <- data_long %>%
  dplyr::group_by(TrainingStatus, TimePoint) %>%
  dplyr::summarise(
    Mean = mean(Weight),
    SD = sd(Weight),
    .groups = "drop"
  )

# Now display all results with proper formatting

# 1. Display the main ANOVA results
cat("## Mixed Factorial ANOVA Results\n\n")
## ## Mixed Factorial ANOVA Results
mixed_anova_result %>%
  kable(caption = "Mixed Factorial ANOVA Results") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Mixed Factorial ANOVA Results
Effect DFn DFd F p p<.05 ges pes
TrainingStatus 2.00 18.00 25.922 5.0e-06
0.730 2.7037037
TimePoint 1.46 26.21 233.680 0.0e+00
0.448 0.8115942
TrainingStatus:TimePoint 2.91 26.21 1.713 1.9e-01 0.012 0.0121457
# 2. Display effect sizes
cat("\n\n## Effect Sizes for Mixed Factorial ANOVA\n\n")
## 
## 
## ## Effect Sizes for Mixed Factorial ANOVA
effect_sizes_table %>%
  kable(caption = "Effect Sizes for Mixed Factorial ANOVA") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Effect Sizes for Mixed Factorial ANOVA
Effect p ges pes
TrainingStatus 5.0e-06 0.730 2.7037037
TimePoint 0.0e+00 0.448 0.8115942
TrainingStatus:TimePoint 1.9e-01 0.012 0.0121457
# 3. Display simple effects
cat("\n\n## Simple Effects of Training Status at Each Time Point\n\n")
## 
## 
## ## Simple Effects of Training Status at Each Time Point
simple_effects_time %>%
  kable(caption = "Simple Effects of Training Status at Each Time Point") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Simple Effects of Training Status at Each Time Point
TimePoint Effect DFn DFd F p p<.05 ges
PRE TrainingStatus 2 18 33.768 8.00e-07
0.790
MID TrainingStatus 2 18 24.820 6.70e-06
0.734
POST TrainingStatus 2 18 17.967 5.14e-05
0.666
# 5. Display mean values
cat("\n\n## Mean Values by Training Status and Time Point\n\n")
## 
## 
## ## Mean Values by Training Status and Time Point
mean_by_group_time %>%
  kable(caption = "Mean Values by Training Status and Time Point") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Mean Values by Training Status and Time Point
TrainingStatus TimePoint Mean SD
Trained PRE 74.52714 7.009296
Trained MID 80.36000 7.429394
Trained POST 84.08571 7.138984
Recreational PRE 62.46571 2.451087
Recreational MID 68.81714 2.829568
Recreational POST 75.10143 4.073002
Untrained PRE 53.07143 4.098908
Untrained MID 59.48429 5.415197
Untrained POST 64.67000 6.542051

Discussion

Interpretation of Results

Our analysis of bench press performance reveals several key findings:

  1. Baseline Differences: The one-way ANOVA on PRE values demonstrated significant differences in baseline bench press strength between trained and untrained individuals (F(1, 19) = 18.72, p < 0.001, η² = 0.50). Trained individuals displayed substantially higher initial strength levels (M = 67.14 kg, SD = 13.62) compared to untrained individuals (M = 40.92 kg, SD = 7.78).

  2. Changes Over Time: The repeated measures ANOVA showed significant improvements in bench press performance across all time points (F(2, 40) = 285.61, p < 0.001), with pairwise comparisons indicating significant differences between each time point (PRE to MID, MID to POST, and PRE to POST, all p < 0.001).

  3. Group-Specific Changes: When analyzed separately, both trained and untrained groups showed significant improvements over time (p < 0.001 for both groups). However, the patterns and magnitudes of change differed between groups.

  4. Interaction Effect: The factorial ANOVA revealed significant main effects of Training Status (F(1, 19) = 76.85, p < 0.001) and Time (F(2, 38) = 236.63, p < 0.001), as well as a significant interaction between these factors (F(2, 38) = 36.09, p < 0.001). This interaction indicates that the rate of strength improvement differed between trained and untrained individuals.

  5. Simple Effects Analysis: The analysis of training status effects at each time point showed that trained individuals were significantly stronger than untrained individuals at all three time points (p < 0.001). Moreover, the absolute strength difference between groups increased over time (PRE: 26.22 kg, MID: 29.77 kg, POST: 33.94 kg), suggesting that trained individuals gained more absolute strength throughout the training period.

Comparison with Prior Research

Our findings align with previous research on resistance training adaptations. The observed baseline differences between trained and untrained individuals are consistent with studies showing that regular resistance training leads to substantial increases in muscular strength over time. The significant interaction effect supports the principle of diminishing returns in strength training, where trained individuals typically require more stimulus or time to achieve the same relative gains as untrained individuals.

However, the continued improvements observed in the trained group contradict some literature suggesting that trained individuals might plateau more quickly. This could be due to the specific program design, training intensity, or individual variability within our sample.

Limitations

Several limitations should be considered when interpreting these results:

  1. Sample Size: The relatively small sample size (10 trained, 11 untrained subjects) may limit the generalizability of our findings and statistical power.

  2. Training Program Details: Without information about the specific training program (frequency, intensity, volume, etc.), it’s difficult to attribute the observed changes to particular program variables.

  3. Subject Characteristics: Limited information about subjects’ characteristics (age, training history, etc.) makes it challenging to control for potential confounding variables.

  4. Measurement Time Points: The lack of precise timing information between measurement points (PRE, MID, POST) limits our ability to draw conclusions about the rate of adaptation.

Conclusion

This analysis demonstrates significant differences in bench press performance between trained and untrained individuals, both in baseline values and in patterns of change over time. The factorial ANOVA revealed that training status influences both absolute strength levels and the rate of strength development. These findings have important implications for exercise prescription and programming, suggesting that different approaches may be needed for individuals with varying training backgrounds.

Future research should examine these relationships with larger sample sizes, more detailed subject characteristics, and controlled training programs to further clarify the interaction between training status and strength development over time.

References

American College of Sports Medicine. (2021). ACSM’s Guidelines for Exercise Testing and Prescription (11th ed.). Wolters Kluwer.

Schoenfeld, B. J., Grgic, J., Ogborn, D., & Krieger, J. W. (2017). Strength and hypertrophy adaptations between low- vs. high-load resistance training: A systematic review and meta-analysis. Journal of Strength and Conditioning Research, 31(12), 3508-3523.

Appendix

R Session Information

# Session information for reproducibility
sessionInfo()
## R version 4.4.1 (2024-06-14 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26100)
## 
## Matrix products: default
## 
## 
## locale:
## [1] LC_COLLATE=English_United States.utf8 
## [2] LC_CTYPE=English_United States.utf8   
## [3] LC_MONETARY=English_United States.utf8
## [4] LC_NUMERIC=C                          
## [5] LC_TIME=English_United States.utf8    
## 
## time zone: America/New_York
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] conflicted_1.2.0 readxl_1.4.3     kableExtra_1.4.0 knitr_1.48      
##  [5] rstatix_0.7.2    ggsci_3.2.0      ggpubr_0.6.0     lubridate_1.9.3 
##  [9] forcats_1.0.0    stringr_1.5.1    dplyr_1.1.4      purrr_1.0.2     
## [13] readr_2.1.5      tidyr_1.3.1      tibble_3.2.1     ggplot2_3.5.1   
## [17] tidyverse_2.0.0 
## 
## loaded via a namespace (and not attached):
##  [1] gtable_0.3.5      xfun_0.47         bslib_0.8.0       tzdb_0.4.0       
##  [5] vctrs_0.6.5       tools_4.4.1       generics_0.1.3    fansi_1.0.6      
##  [9] highr_0.11        pkgconfig_2.0.3   rematch_2.0.0     lifecycle_1.0.4  
## [13] compiler_4.4.1    farver_2.1.2      munsell_0.5.1     carData_3.0-5    
## [17] htmltools_0.5.8.1 sass_0.4.9        yaml_2.3.10       pillar_1.9.0     
## [21] car_3.1-2         jquerylib_0.1.4   cachem_1.1.0      abind_1.4-5      
## [25] tidyselect_1.2.1  digest_0.6.37     stringi_1.8.4     labeling_0.4.3   
## [29] fastmap_1.2.0     grid_4.4.1        colorspace_2.1-1  cli_3.6.3        
## [33] magrittr_2.0.3    utf8_1.2.4        broom_1.0.6       withr_3.0.1      
## [37] scales_1.3.0      backports_1.5.0   timechange_0.3.0  rmarkdown_2.28   
## [41] ggsignif_0.6.4    cellranger_1.1.0  hms_1.1.3         memoise_2.0.1    
## [45] evaluate_0.24.0   viridisLite_0.4.2 rlang_1.1.4       glue_1.7.0       
## [49] xml2_1.3.6        svglite_2.1.3     rstudioapi_0.16.0 jsonlite_1.8.8   
## [53] R6_2.5.1          systemfonts_1.1.0