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 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 |
# 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)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"))| 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 |
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).
# 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 |
# 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
# 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
# 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 |
# 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"
)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.
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).
# 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)| 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)| 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)| 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 |
# 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
))
}# Analyze all three datasets and store complete results
results1 <- analyze_reliability(set1_data, "1 (Original)")## ## Analysis for Dataset 1 (Original)
## ## Analysis for Dataset 2 (Higher Consistency)
## ## 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 |
## ### 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 |
## ### 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 |
## ### Visualization
## ### 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 |
## ### 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 |
## ### 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 |
## ### Visualization
## ### 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 |
## ### 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 |
## ### 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 |
## ### Visualization
# 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"
)The analysis of the three datasets with varying levels of data consistency demonstrates how reliability metrics are affected by changes in data variability:
Dataset 1 (Original): This dataset serves as our baseline with moderate reliability.
Dataset 2 (Higher Consistency): This dataset shows higher consistency between trials for each subject. As a result:
Dataset 3 (Greater Variability): This dataset demonstrates increased variability between both subjects and trials. As a result:
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.
When reporting reliability metrics to principal investigators, the following considerations are important:
ICC Interpretation:
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.
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.
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.
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: - 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)
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.
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.
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.
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.
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:
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.
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.
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.
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 |
## 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 |
# 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 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)| 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)| 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 |
# 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)# 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)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)| 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)| 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)| 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)| 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 | ** |
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)| 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)| 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)| .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 | **** |
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)| 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)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)| 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 |
##
##
## ## 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 | 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 |
##
##
## ## 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)| 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 |
##
##
## ## 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)| 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 |
Our analysis of bench press performance reveals several key findings:
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).
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).
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.
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.
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.
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.
Several limitations should be considered when interpreting these results:
Sample Size: The relatively small sample size (10 trained, 11 untrained subjects) may limit the generalizability of our findings and statistical power.
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.
Subject Characteristics: Limited information about subjects’ characteristics (age, training history, etc.) makes it challenging to control for potential confounding variables.
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.
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.
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.
## 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