This analysis examines pulmonary function test (PFT) data across three time periods: - PRE: Pre-pandemic - PAN: During pandemic - POST: Post-pandemic
We will perform: 1. One-way ANOVA for continuous variables (FVC%, FVC Absolute, FEV1%, FEV1 Absolute, FEV1/FVC) 2. Chi-squared test for categorical variable (Sawtooth Pattern presence)
library(tidyverse)
library(car)
library(ggplot2)
library(gridExtra)
library(knitr)
library(broom)
fvc_percent_pre <- c(1.125827815, 0.8934579439, 1.001751313, 1.138028169, 0.9933628319,
1.023622047, 1.015250545, 1.041436464, 1.202087287, 1.210268949,
1.130319149, 1.001312336, 1.15530303, 1.30945122, 1.080615942,
1.116972477, 1.136075949, 0.9304511278, 1.154022989, 0.9736842105,
0.8197969543, 1.063829787, 1.07745098, 1.178149606, 1.169340463,
1.186725664, 1.077108434, 1.23853211, 1.090196078, 1.248511905,
1.016055046, 1.041845494, 1.14, 1.167481663, 1.082236842,
0.9478527607, 0.9860426929, 1.2079566, 1.340753425, 1.017751479,
0.9667832168, 1.171428571, 1.173486088, 0.9443493151, 0.885286783,
1.05511811, 0.8910550459, 0.6631205674, 1.075875486, 1.112944162,
1.120171674)
fvc_percent_pan <- c(1.073563218, 1.050245098, 0.8611987382, 1.343010753, 1.018446602,
0.957337884, 1, 1.169054441, 0.8679245283, 1.042009885,
1.085280374, 0.9787018256, 1.036666667, 1.061611374, 0.9673659674,
1.098669623, 1.109289617, 0.9569160998, 0.8655172414, 1.102134146,
1.093478261, 0.9368932039, 0.8425287356, 0.8228643216, 0.4581632653,
1.040772532, 0.8959435626, 0.9973544974, 1.00776699, 0.9832935561,
1.073253833, 1.15, 1.03490566, 0.9513556619, 1.100543478,
0.8669656203, 1.003773585, 1.17414248, 1.081613508, 0.9090909091,
1.019699812, 1.067028986, 1.138086643, 1.457236842, 1.055405405,
1.037694013, 1.056872038, 1.050713154, 0.9340490798, 1.0225,
1.216066482)
fvc_percent_post <- c(1.032062392, 1.029484029, 0.9576659039, 1.214650767, 0.9807302231,
1.213207547, 0.9259259259, 1.03436019, 1.254452926, 1.081771721,
0.8295165394, 1.083333333, 1.031806616, 0.6995412844, 0.9435483871,
1.443064182, 1.191295547, 1.066157761, 0.9398034398, 1.107583774,
0.883248731, 1.224683544, 1.073015873, 1.106617647, 1.132379249,
0.9255150555, 0.9561403509, 1.239669421, 1.063451777, 1.094202899,
1.010141988, 0.9141791045, 1.086288416, 1, 1.069852941,
1.164691943, 0.9885496183, 0.8510802469, 0.9197080292, 1.23875,
1.081743869, 1.014251781, 0.9775725594, 1.075, 1.011930586,
1.092819615, 0.83847981, 1.190239044, 1.095823096, 0.7485928705,
1.15049505, 0.9677754678, 1.00525394, 1.119089317, 0.7622820919,
0.9567901235, 0.9557522124, 1.061165049, 0.9966159052, 0.8880070547,
1.003623188, 0.8348765432, 0.8955223881, 1.152061856, 1.067681895,
1.064367816, 0.9527145359, 0.8631840796, 1.158119658, 1.053333333,
1.088832487, 1.096226415, 0.8657894737, 0.7826086957, 1.203448276,
0.937037037, 1.03562341, 1.079422383, 1.019417476, 1.453125,
1.195911414, 0.9459102902, 1.190709046, 1.031301483, 0.7691588785,
0.8957783641, 0.7240527183, 0.92228739, 0.9637681159, 0.9796954315,
0.9565789474, 1.03785489, 0.9105263158)
fvc_percent <- data.frame(
Period = c(rep("PRE", length(fvc_percent_pre)),
rep("PAN", length(fvc_percent_pan)),
rep("POST", length(fvc_percent_post))),
Value = c(fvc_percent_pre, fvc_percent_pan, fvc_percent_post)
) %>%
mutate(Period = factor(Period, levels = c("PRE", "PAN", "POST")))
fvc_absolute_pre <- c(3.4, 4.78, 5.72, 4.04, 4.49, 3.9, 4.66, 3.77, 6.335, 4.95,
4.25, 3.815, 4.575, 4.295, 5.965, 4.87, 5.385, 4.95, 5.02, 3.7,
3.23, 4, 5.495, 5.985, 6.56, 6.705, 4.47, 5.4, 5.56, 4.195,
4.43, 4.855, 3.99, 4.775, 6.58, 3.09, 6.005, 6.68, 7.83, 3.44,
5.53, 4.1, 7.17, 5.515, 3.55, 4.02, 3.885, 3.74, 5.53, 4.385,
5.22)
fvc_absolute_pan <- c(4.67, 4.285, 5.46, 6.245, 5.245, 5.61, 5.3, 4.08, 4.6, 6.325,
4.645, 4.825, 4.665, 4.48, 4.15, 4.955, 4.06, 4.22, 3.765, 3.615,
7.55, 4.825, 3.665, 3.275, 2.245, 4.85, 5.08, 3.77, 5.19, 4.12,
6.3, 6.095, 5.49, 5.965, 6.075, 5.8, 5.32, 4.45, 5.765, 2.9,
5.435, 5.89, 6.305, 4.43, 3.905, 4.68, 4.46, 6.63, 3.045, 4.09,
4.39)
fvc_absolute_post <- c(5.955, 4.19, 4.185, 7.13, 4.835, 6.43, 6, 4.365, 4.93, 6.35,
3.26, 3.965, 4.055, 3.05, 4.68, 6.97, 5.885, 4.19, 3.825, 6.28,
5.22, 5.805, 3.38, 4.515, 6.33, 5.84, 5.995, 4.5, 4.19, 6.04,
4.98, 3.675, 4.595, 3.41, 4.365, 4.915, 3.885, 5.515, 5.04, 4.955,
3.97, 4.27, 3.705, 6.45, 4.665, 6.24, 3.53, 5.975, 4.46, 3.99,
5.81, 4.655, 5.74, 6.39, 4.81, 5.425, 4.32, 5.465, 5.89, 5.035,
6.925, 5.41, 4.8, 6.705, 6.31, 4.63, 5.44, 3.47, 4.065, 4.74,
4.29, 5.81, 3.29, 4.32, 5.235, 5.06, 4.07, 5.98, 5.25, 6.51,
7.02, 3.585, 4.87, 6.26, 4.115, 3.395, 4.395, 3.145, 5.32,
5.79, 3.635, 6.58, 3.46)
fvc_absolute <- data.frame(
Period = c(rep("PRE", length(fvc_absolute_pre)),
rep("PAN", length(fvc_absolute_pan)),
rep("POST", length(fvc_absolute_post))),
Value = c(fvc_absolute_pre, fvc_absolute_pan, fvc_absolute_post)
) %>%
mutate(Period = factor(Period, levels = c("PRE", "PAN", "POST")))
fev1_percent_pre <- c(0.9759259259, 0.8509933775, 0.9802904564, 0.9870967742, 1.037275064,
1.055891239, 0.9987531172, 0.9921875, 1.227171492, 1.143258427,
1.096969697, 1.027108434, 1.130813953, 1.227739726, 0.8683083512,
1.080687831, 1.153186275, 0.7605321508, 0.9498680739, 0.9234234234,
0.8226744186, 1.036363636, 1.104597701, 1.101149425, 1.180293501,
1.107740586, 1.02892562, 1.169312169, 1.049425287, 1.258333333,
1.005291005, 1.002487562, 1.211290323, 1.171875, 0.9774951076,
0.9597902098, 0.8857421875, 1.128479657, 1.076219512, 0.9598662207,
0.8226141079, 1.119354839, 1.153996101, 1.071283096, 0.9419263456,
1.063253012, 0.8902116402, 0.8221757322, 1.02283105, 0.8648255814,
1.012437811)
fev1_percent_pan <- c(1.116094987, 0.9788732394, 0.8371212121, 0.8660049628, 0.997716895,
0.9716024341, 1.002222222, 1.035483871, 0.8155555556, 0.7941176471,
1.089333333, 0.9265402844, 0.9654731458, 0.8160762943, 0.9,
1.034615385, 0.9068322981, 1.058139535, 0.8562005277, 1.05862069,
0.8886956522, 0.7694063927, 0.7189973615, 0.8614285714, 0.3627684964,
1.099502488, 0.9125, 0.963963964, 0.9285714286, 1.021798365,
0.6232323232, 1.112222222, 1, 0.9058935361, 1.003211991,
0.8422939068, 1.006666667, 1.073573574, 1.064301552, 0.9642857143,
0.9723451327, 1.026766595, 1.048179872, 1.383333333, 1.043209877,
1.016666667, 0.9972752044, 0.8816287879, 0.9775862069, 0.9114285714,
1.174050633)
fev1_percent_post <- c(0.9630390144, 0.9225352113, 0.8422459893, 1.201010101, 0.9952606635,
1.213333333, 1.046125461, 1.054347826, 1.300872093, 1.062626263,
0.8880813953, 1.096273292, 1.049418605, 0.7552910053, 0.9549763033,
1.498783455, 1.04009434, 1.11627907, 0.9957746479, 1.114583333,
0.9436619718, 1.243872549, 1.041666667, 1.004225352, 1.053571429,
0.7755681818, 0.8108365019, 1.059375, 1.064841499, 0.9421841542,
0.990521327, 0.9670487106, 0.900273224, 0.8183333333, 1.009859155,
1.108991826, 0.7456395349, 0.8118081181, 0.9849462366, 1.144475921,
1.040372671, 1.032697548, 1.016516517, 1.015810277, 0.9409638554,
1.102697095, 0.89373297, 1.096736597, 1.177464789, 0.7212389381,
1.024249423, 0.9939759036, 1.031120332, 1.064315353, 0.7547348485,
0.9, 1.014248705, 0.997716895, 0.9839034205, 0.696875, 0.9426086957,
0.8256457565, 0.9303097345, 1.032064128, 1.020120724, 0.9406332454,
0.9139004149, 0.8567335244, 1.16828479, 1.034526854, 1.068313953,
1.104444444, 0.7717717718, 0.8286937901, 1.211081794, 0.9287280702,
1.066860465, 0.9646680942, 1.020547945, 1.3671875, 1.135353535,
0.9624624625, 1.110169492, 1.019607843, 0.7953539823, 0.9294294294,
0.8352941176, 0.9783333333, 1.027837259, 1.044265594, 0.966966967,
1.035984848, 0.987987988)
fev1_percent <- data.frame(
Period = c(rep("PRE", length(fev1_percent_pre)),
rep("PAN", length(fev1_percent_pan)),
rep("POST", length(fev1_percent_post))),
Value = c(fev1_percent_pre, fev1_percent_pan, fev1_percent_post)
) %>%
mutate(Period = factor(Period, levels = c("PRE", "PAN", "POST")))
fev1_absolute_pre <- c(2.635, 3.855, 4.725, 3.06, 4.035, 3.495, 4.005, 3.175, 5.51, 4.07,
3.62, 3.41, 3.89, 3.585, 4.055, 4.085, 4.705, 3.43, 3.6, 3.075,
2.83, 3.42, 4.805, 4.79, 5.63, 5.295, 3.735, 4.42, 4.565, 3.775,
3.8, 4.03, 3.755, 4.125, 4.995, 2.745, 4.535, 5.27, 5.295, 2.87,
3.965, 3.47, 5.92, 5.26, 3.325, 3.53, 3.365, 3.93, 4.48, 2.975,
4.07)
fev1_absolute_pan <- c(4.23, 3.475, 4.42, 3.49, 4.37, 4.79, 4.51, 3.21, 3.67, 4.05,
4.085, 3.91, 3.775, 2.995, 3.375, 4.035, 2.92, 4.095, 3.245, 3.07,
5.11, 3.37, 2.725, 3.015, 1.52, 4.42, 4.38, 3.21, 4.095, 3.75,
3.085, 5.005, 4.5, 4.765, 4.685, 4.7, 4.53, 3.575, 4.8, 2.565,
4.395, 4.795, 4.895, 3.735, 3.38, 3.965, 3.66, 4.655, 2.835, 3.19,
3.71)
fev1_absolute_post <- c(4.69, 3.275, 3.15, 5.945, 4.2, 5.46, 5.67, 3.88, 4.475, 5.26,
3.055, 3.53, 3.61, 2.855, 4.03, 6.16, 4.41, 3.84, 3.535, 5.35,
4.69, 5.075, 2.875, 3.565, 5.015, 4.095, 4.265, 3.39, 3.695, 4.4,
4.18, 3.375, 3.295, 2.455, 3.585, 4.07, 2.565, 4.4, 4.58, 4.04,
3.35, 3.79, 3.385, 5.14, 3.905, 5.315, 3.28, 4.705, 4.18, 3.26,
4.435, 4.125, 4.97, 5.13, 3.985, 4.32, 3.915, 4.37, 4.89, 3.345,
5.42, 4.475, 4.205, 5.15, 5.07, 3.565, 4.405, 2.99, 3.61, 4.045,
3.675, 4.97, 2.57, 3.87, 4.59, 4.235, 3.67, 4.505, 4.47, 5.25,
5.62, 3.205, 3.93, 5.2, 3.595, 3.095, 4.26, 2.935, 4.8, 5.19,
3.22, 5.47, 3.29)
fev1_absolute <- data.frame(
Period = c(rep("PRE", length(fev1_absolute_pre)),
rep("PAN", length(fev1_absolute_pan)),
rep("POST", length(fev1_absolute_post))),
Value = c(fev1_absolute_pre, fev1_absolute_pan, fev1_absolute_post)
) %>%
mutate(Period = factor(Period, levels = c("PRE", "PAN", "POST")))
fev1_fvc_ratio_pre <- c(87, 81, 83, 76, 90, 90, 87, 84, 87, 82, 85, 89.5, 85, 83, 68, 84,
87.5, 69.5, 81, 84, 87.5, 86, 87.5, 80, 86, 82, 83.5, 83, 82, 90,
86, 82, 94, 86.5, 76, 88.5, 75.5, 79, 72, 83, 71.5, 85, 82.5, 95.5,
94.5, 88, 86.5, 68, 81, 69.5, 80)
fev1_fvc_ratio_pan <- c(91, 89, 83, 86, 83.5, 85.5, 78, 78.5, 81, 64, 88, 81, 81, 67, 81.5,
81.5, 72, 97, 86.5, 85, 67.5, 69.5, 74.5, 92, 72.5, 91, 86, 85, 79,
91, 49, 82, 82, 79.5, 77, 81, 85.5, 80.5, 83, 88.5, 81, 81.5, 78,
84, 87, 84.5, 82.5, 70.5, 93, 78, 84.5)
fev1_fvc_ratio_post <- c(79, 78, 75.5, 83.5, 87, 85, 95, 88.5, 90.5, 83, 94, 94.5, 88.5, 93.5,
86, 88, 75, 92, 92.5, 85, 89, 87, 85, 79, 79, 70, 71, 75, 87.5, 73,
84, 91.5, 71.5, 72, 82, 83, 66, 80, 91, 81.5, 84, 89, 91.5, 79.5,
84, 85.5, 92.5, 79, 94, 81.5, 76.5, 88.5, 87, 80, 83, 79.5, 90.5,
80, 83, 66.5, 78.5, 82.5, 87.5, 77, 80.5, 77, 81, 86, 88.5, 85.5,
85.5, 86, 78.5, 90, 88, 84, 90, 75.5, 85, 81, 80, 90, 81, 83, 87,
91.5, 97, 93.5, 90, 90, 88.5, 83, 95)
fev1_fvc_ratio <- data.frame(
Period = c(rep("PRE", length(fev1_fvc_ratio_pre)),
rep("PAN", length(fev1_fvc_ratio_pan)),
rep("POST", length(fev1_fvc_ratio_post))),
Value = c(fev1_fvc_ratio_pre, fev1_fvc_ratio_pan, fev1_fvc_ratio_post)
) %>%
mutate(Period = factor(Period, levels = c("PRE", "PAN", "POST")))
sawtooth_data <- data.frame(
Period = c("PRE", "PAN", "POST"),
Present = c(12, 30, 41),
Total = c(51, 51, 93),
Absent = c(51-12, 51-30, 93-41)
)
sawtooth_data$Percent <- (sawtooth_data$Present / sawtooth_data$Total) * 100
get_summary_stats <- function(data, variable_name) {
summary_stats <- data %>%
group_by(Period) %>%
summarise(
N = n(),
Mean = mean(Value),
SD = sd(Value),
Median = median(Value),
Min = min(Value),
Max = max(Value),
.groups = 'drop'
)
return(summary_stats)
}
fvc_pct_summary <- get_summary_stats(fvc_percent, "FVC%")
kable(fvc_pct_summary, digits = 3, caption = "Summary Statistics for FVC%")
| Period | N | Mean | SD | Median | Min | Max |
|---|---|---|---|---|---|---|
| PRE | 51 | 1.074 | 0.125 | 1.081 | 0.663 | 1.341 |
| PAN | 51 | 1.022 | 0.142 | 1.037 | 0.458 | 1.457 |
| POST | 93 | 1.023 | 0.139 | 1.029 | 0.700 | 1.453 |
fvc_abs_summary <- get_summary_stats(fvc_absolute, "FVC Absolute")
kable(fvc_abs_summary, digits = 3, caption = "Summary Statistics for FVC Absolute Average")
| Period | N | Mean | SD | Median | Min | Max |
|---|---|---|---|---|---|---|
| PRE | 51 | 4.878 | 1.097 | 4.775 | 3.090 | 7.83 |
| PAN | 51 | 4.847 | 1.053 | 4.680 | 2.245 | 7.55 |
| POST | 93 | 4.972 | 1.064 | 4.870 | 3.050 | 7.13 |
fev1_pct_summary <- get_summary_stats(fev1_percent, "FEV1%")
kable(fev1_pct_summary, digits = 3, caption = "Summary Statistics for FEV1%")
| Period | N | Mean | SD | Median | Min | Max |
|---|---|---|---|---|---|---|
| PRE | 51 | 1.029 | 0.119 | 1.029 | 0.761 | 1.258 |
| PAN | 51 | 0.953 | 0.149 | 0.972 | 0.363 | 1.383 |
| POST | 93 | 0.998 | 0.137 | 1.010 | 0.697 | 1.499 |
fev1_abs_summary <- get_summary_stats(fev1_absolute, "FEV1 Absolute")
kable(fev1_abs_summary, digits = 3, caption = "Summary Statistics for FEV1 Absolute Average")
| Period | N | Mean | SD | Median | Min | Max |
|---|---|---|---|---|---|---|
| PRE | 51 | 4.020 | 0.805 | 3.930 | 2.635 | 5.92 |
| PAN | 51 | 3.858 | 0.754 | 3.910 | 1.520 | 5.11 |
| POST | 93 | 4.154 | 0.834 | 4.125 | 2.455 | 6.16 |
ratio_summary <- get_summary_stats(fev1_fvc_ratio, "FEV1/FVC")
kable(ratio_summary, digits = 3, caption = "Summary Statistics for FEV1/FVC Ratio")
| Period | N | Mean | SD | Median | Min | Max |
|---|---|---|---|---|---|---|
| PRE | 51 | 83.049 | 6.483 | 84 | 68 | 95.5 |
| PAN | 51 | 81.186 | 8.264 | 82 | 49 | 97.0 |
| POST | 93 | 84.129 | 6.676 | 85 | 66 | 97.0 |
kable(sawtooth_data, digits = 2, caption = "Sawtooth Pattern Presence by Period")
| Period | Present | Total | Absent | Percent |
|---|---|---|---|---|
| PRE | 12 | 51 | 39 | 23.53 |
| PAN | 30 | 51 | 21 | 58.82 |
| POST | 41 | 93 | 52 | 44.09 |
perform_anova <- function(data, test_name) {
anova_result <- aov(Value ~ Period, data = data)
levene_test <- leveneTest(Value ~ Period, data = data)
tukey_result <- TukeyHSD(anova_result)
results <- list(
test_name = test_name,
data = data,
anova = anova_result,
anova_summary = summary(anova_result),
levene = levene_test,
tukey = tukey_result
)
return(results)
}
fvc_pct_anova <- perform_anova(fvc_percent, "FVC%")
cat("\n=== FVC% ANOVA Results ===\n")
##
## === FVC% ANOVA Results ===
print(fvc_pct_anova$anova_summary)
## Df Sum Sq Mean Sq F value Pr(>F)
## Period 2 0.101 0.05048 2.707 0.0693 .
## Residuals 192 3.581 0.01865
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("\n--- Levene's Test for Homogeneity of Variance ---\n")
##
## --- Levene's Test for Homogeneity of Variance ---
print(fvc_pct_anova$levene)
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 2 0.4401 0.6446
## 192
cat("\n--- Tukey HSD Post-Hoc Test ---\n")
##
## --- Tukey HSD Post-Hoc Test ---
print(fvc_pct_anova$tukey)
## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov(formula = Value ~ Period, data = data)
##
## $Period
## diff lwr upr p adj
## PAN-PRE -0.0522654627 -0.11614857 0.011617650 0.1323690
## POST-PRE -0.0515032364 -0.10771288 0.004706408 0.0800368
## POST-PAN 0.0007622263 -0.05544742 0.056971871 0.9994345
fvc_abs_anova <- perform_anova(fvc_absolute, "FVC Absolute")
cat("\n=== FVC Absolute ANOVA Results ===\n")
##
## === FVC Absolute ANOVA Results ===
print(fvc_abs_anova$anova_summary)
## Df Sum Sq Mean Sq F value Pr(>F)
## Period 2 0.6 0.3016 0.263 0.769
## Residuals 192 219.9 1.1452
cat("\n--- Levene's Test for Homogeneity of Variance ---\n")
##
## --- Levene's Test for Homogeneity of Variance ---
print(fvc_abs_anova$levene)
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 2 0.1934 0.8243
## 192
cat("\n--- Tukey HSD Post-Hoc Test ---\n")
##
## --- Tukey HSD Post-Hoc Test ---
print(fvc_abs_anova$tukey)
## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov(formula = Value ~ Period, data = data)
##
## $Period
## diff lwr upr p adj
## PAN-PRE -0.03137255 -0.5319338 0.4691887 0.9879912
## POST-PRE 0.09332385 -0.3471113 0.5337590 0.8711591
## POST-PAN 0.12469639 -0.3157388 0.5651316 0.7819119
fev1_pct_anova <- perform_anova(fev1_percent, "FEV1%")
cat("\n=== FEV1% ANOVA Results ===\n")
##
## === FEV1% ANOVA Results ===
print(fev1_pct_anova$anova_summary)
## Df Sum Sq Mean Sq F value Pr(>F)
## Period 2 0.152 0.07623 4.113 0.0178 *
## Residuals 192 3.559 0.01853
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("\n--- Levene's Test for Homogeneity of Variance ---\n")
##
## --- Levene's Test for Homogeneity of Variance ---
print(fev1_pct_anova$levene)
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 2 0.0883 0.9156
## 192
cat("\n--- Tukey HSD Post-Hoc Test ---\n")
##
## --- Tukey HSD Post-Hoc Test ---
print(fev1_pct_anova$tukey)
## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov(formula = Value ~ Period, data = data)
##
## $Period
## diff lwr upr p adj
## PAN-PRE -0.07661438 -0.14029502 -0.01293374 0.0137172
## POST-PRE -0.03073542 -0.08676692 0.02529607 0.3993469
## POST-PAN 0.04587896 -0.01015254 0.10191045 0.1319423
fev1_abs_anova <- perform_anova(fev1_absolute, "FEV1 Absolute")
cat("\n=== FEV1 Absolute ANOVA Results ===\n")
##
## === FEV1 Absolute ANOVA Results ===
print(fev1_abs_anova$anova_summary)
## Df Sum Sq Mean Sq F value Pr(>F)
## Period 2 2.93 1.464 2.253 0.108
## Residuals 192 124.80 0.650
cat("\n--- Levene's Test for Homogeneity of Variance ---\n")
##
## --- Levene's Test for Homogeneity of Variance ---
print(fev1_abs_anova$levene)
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 2 0.3855 0.6807
## 192
cat("\n--- Tukey HSD Post-Hoc Test ---\n")
##
## --- Tukey HSD Post-Hoc Test ---
print(fev1_abs_anova$tukey)
## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov(formula = Value ~ Period, data = data)
##
## $Period
## diff lwr upr p adj
## PAN-PRE -0.1618627 -0.53898240 0.2152569 0.5690565
## POST-PRE 0.1346300 -0.19719107 0.4664510 0.6040750
## POST-PAN 0.2964927 -0.03532833 0.6283138 0.0903550
ratio_anova <- perform_anova(fev1_fvc_ratio, "FEV1/FVC Ratio")
cat("\n=== FEV1/FVC Ratio ANOVA Results ===\n")
##
## === FEV1/FVC Ratio ANOVA Results ===
print(ratio_anova$anova_summary)
## Df Sum Sq Mean Sq F value Pr(>F)
## Period 2 285 142.64 2.848 0.0604 .
## Residuals 192 9617 50.09
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("\n--- Levene's Test for Homogeneity of Variance ---\n")
##
## --- Levene's Test for Homogeneity of Variance ---
print(ratio_anova$levene)
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 2 0.4863 0.6156
## 192
cat("\n--- Tukey HSD Post-Hoc Test ---\n")
##
## --- Tukey HSD Post-Hoc Test ---
print(ratio_anova$tukey)
## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov(formula = Value ~ Period, data = data)
##
## $Period
## diff lwr upr p adj
## PAN-PRE -1.862745 -5.17310481 1.447615 0.3807819
## POST-PRE 1.080013 -1.83271556 3.992741 0.6561971
## POST-PAN 2.942758 0.03002954 5.855486 0.0470644
sawtooth_matrix <- matrix(c(sawtooth_data$Present, sawtooth_data$Absent),
nrow = 3, byrow = FALSE,
dimnames = list(Period = c("PRE", "PAN", "POST"),
Pattern = c("Present", "Absent")))
cat("\n=== Contingency Table ===\n")
##
## === Contingency Table ===
print(sawtooth_matrix)
## Pattern
## Period Present Absent
## PRE 12 39
## PAN 30 21
## POST 41 52
# Chi-squared test
chi_sq_result <- chisq.test(sawtooth_matrix)
cat("\n=== Chi-Squared Test Results ===\n")
##
## === Chi-Squared Test Results ===
print(chi_sq_result)
##
## Pearson's Chi-squared test
##
## data: sawtooth_matrix
## X-squared = 13.162, df = 2, p-value = 0.001387
# Expected frequencies
cat("\n--- Expected Frequencies ---\n")
##
## --- Expected Frequencies ---
print(chi_sq_result$expected)
## Pattern
## Period Present Absent
## PRE 21.70769 29.29231
## PAN 21.70769 29.29231
## POST 39.58462 53.41538
# Standardized residuals
cat("\n--- Standardized Residuals ---\n")
##
## --- Standardized Residuals ---
print(chi_sq_result$stdres)
## Pattern
## Period Present Absent
## PRE -3.1992894 3.1992894
## PAN 2.7328320 -2.7328320
## POST 0.4104278 -0.4104278
p1 <- ggplot(fvc_pct_anova$data, aes(x = Period, y = Value, fill = Period)) +
geom_boxplot(alpha = 0.7) +
geom_jitter(width = 0.2, alpha = 0.3) +
scale_fill_manual(values = c("PRE" = "#2E86AB", "PAN" = "#A23B72", "POST" = "#F18F01")) +
labs(title = "FVC% by Period", y = "FVC%", x = "Period") +
theme_minimal() +
theme(legend.position = "none",
plot.title = element_text(hjust = 0.5, face = "bold"))
p2 <- ggplot(fvc_pct_summary, aes(x = Period, y = Mean, group = 1)) +
geom_line(color = "#2E86AB", size = 1.2) +
geom_point(size = 3, color = "#2E86AB") +
geom_errorbar(aes(ymin = Mean - SD, ymax = Mean + SD), width = 0.2) +
labs(title = "Mean FVC% with Standard Deviation", y = "Mean FVC%", x = "Period") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))
grid.arrange(p1, p2, ncol = 1)
p1 <- ggplot(fvc_abs_anova$data, aes(x = Period, y = Value, fill = Period)) +
geom_boxplot(alpha = 0.7) +
geom_jitter(width = 0.2, alpha = 0.3) +
scale_fill_manual(values = c("PRE" = "#2E86AB", "PAN" = "#A23B72", "POST" = "#F18F01")) +
labs(title = "FVC Absolute by Period", y = "FVC (L)", x = "Period") +
theme_minimal() +
theme(legend.position = "none",
plot.title = element_text(hjust = 0.5, face = "bold"))
p2 <- ggplot(fvc_abs_summary, aes(x = Period, y = Mean, group = 1)) +
geom_line(color = "#2E86AB", size = 1.2) +
geom_point(size = 3, color = "#2E86AB") +
geom_errorbar(aes(ymin = Mean - SD, ymax = Mean + SD), width = 0.2) +
labs(title = "Mean FVC Absolute with Standard Deviation", y = "Mean FVC (L)", x = "Period") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))
grid.arrange(p1, p2, ncol = 1)
p1 <- ggplot(fev1_pct_anova$data, aes(x = Period, y = Value, fill = Period)) +
geom_boxplot(alpha = 0.7) +
geom_jitter(width = 0.2, alpha = 0.3) +
scale_fill_manual(values = c("PRE" = "#2E86AB", "PAN" = "#A23B72", "POST" = "#F18F01")) +
labs(title = "FEV1% by Period", y = "FEV1%", x = "Period") +
theme_minimal() +
theme(legend.position = "none",
plot.title = element_text(hjust = 0.5, face = "bold"))
p2 <- ggplot(fev1_pct_summary, aes(x = Period, y = Mean, group = 1)) +
geom_line(color = "#2E86AB", size = 1.2) +
geom_point(size = 3, color = "#2E86AB") +
geom_errorbar(aes(ymin = Mean - SD, ymax = Mean + SD), width = 0.2) +
labs(title = "Mean FEV1% with Standard Deviation", y = "Mean FEV1%", x = "Period") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))
grid.arrange(p1, p2, ncol = 1)
p1 <- ggplot(fev1_abs_anova$data, aes(x = Period, y = Value, fill = Period)) +
geom_boxplot(alpha = 0.7) +
geom_jitter(width = 0.2, alpha = 0.3) +
scale_fill_manual(values = c("PRE" = "#2E86AB", "PAN" = "#A23B72", "POST" = "#F18F01")) +
labs(title = "FEV1 Absolute by Period", y = "FEV1 (L)", x = "Period") +
theme_minimal() +
theme(legend.position = "none",
plot.title = element_text(hjust = 0.5, face = "bold"))
p2 <- ggplot(fev1_abs_summary, aes(x = Period, y = Mean, group = 1)) +
geom_line(color = "#2E86AB", size = 1.2) +
geom_point(size = 3, color = "#2E86AB") +
geom_errorbar(aes(ymin = Mean - SD, ymax = Mean + SD), width = 0.2) +
labs(title = "Mean FEV1 Absolute with Standard Deviation", y = "Mean FEV1 (L)", x = "Period") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))
grid.arrange(p1, p2, ncol = 1)
p1 <- ggplot(ratio_anova$data, aes(x = Period, y = Value, fill = Period)) +
geom_boxplot(alpha = 0.7) +
geom_jitter(width = 0.2, alpha = 0.3) +
scale_fill_manual(values = c("PRE" = "#2E86AB", "PAN" = "#A23B72", "POST" = "#F18F01")) +
labs(title = "FEV1/FVC Ratio by Period", y = "FEV1/FVC (%)", x = "Period") +
theme_minimal() +
theme(legend.position = "none",
plot.title = element_text(hjust = 0.5, face = "bold"))
p2 <- ggplot(ratio_summary, aes(x = Period, y = Mean, group = 1)) +
geom_line(color = "#2E86AB", size = 1.2) +
geom_point(size = 3, color = "#2E86AB") +
geom_errorbar(aes(ymin = Mean - SD, ymax = Mean + SD), width = 0.2) +
labs(title = "Mean FEV1/FVC Ratio with Standard Deviation", y = "Mean FEV1/FVC (%)", x = "Period") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))
grid.arrange(p1, p2, ncol = 1)
# Bar plot with percentages
p1 <- ggplot(sawtooth_data, aes(x = Period, y = Percent, fill = Period)) +
geom_bar(stat = "identity", alpha = 0.7) +
geom_text(aes(label = sprintf("%.1f%%", Percent)), vjust = -0.5, size = 4) +
scale_fill_manual(values = c("PRE" = "#2E86AB", "PAN" = "#A23B72", "POST" = "#F18F01")) +
labs(title = "Sawtooth Pattern Prevalence by Period",
y = "Percentage with Pattern (%)", x = "Period") +
ylim(0, 70) +
theme_minimal() +
theme(legend.position = "none",
plot.title = element_text(hjust = 0.5, face = "bold"))
sawtooth_long <- sawtooth_data %>%
select(Period, Present, Absent) %>%
pivot_longer(cols = c(Present, Absent), names_to = "Pattern", values_to = "Count")
p2 <- ggplot(sawtooth_long, aes(x = Period, y = Count, fill = Pattern)) +
geom_bar(stat = "identity", position = "fill") +
scale_fill_manual(values = c("Present" = "#E63946", "Absent" = "#A8DADC")) +
scale_y_continuous(labels = scales::percent) +
labs(title = "Sawtooth Pattern Distribution",
y = "Proportion", x = "Period") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))
grid.arrange(p1, p2, ncol = 1)
anova_summary_table <- data.frame(
Variable = c("FVC%", "FVC Absolute", "FEV1%", "FEV1 Absolute", "FEV1/FVC Ratio"),
F_Statistic = c(
summary(fvc_pct_anova$anova)[[1]]$`F value`[1],
summary(fvc_abs_anova$anova)[[1]]$`F value`[1],
summary(fev1_pct_anova$anova)[[1]]$`F value`[1],
summary(fev1_abs_anova$anova)[[1]]$`F value`[1],
summary(ratio_anova$anova)[[1]]$`F value`[1]
),
P_Value = c(
summary(fvc_pct_anova$anova)[[1]]$`Pr(>F)`[1],
summary(fvc_abs_anova$anova)[[1]]$`Pr(>F)`[1],
summary(fev1_pct_anova$anova)[[1]]$`Pr(>F)`[1],
summary(fev1_abs_anova$anova)[[1]]$`Pr(>F)`[1],
summary(ratio_anova$anova)[[1]]$`Pr(>F)`[1]
),
Significant = c(
summary(fvc_pct_anova$anova)[[1]]$`Pr(>F)`[1] < 0.05,
summary(fvc_abs_anova$anova)[[1]]$`Pr(>F)`[1] < 0.05,
summary(fev1_pct_anova$anova)[[1]]$`Pr(>F)`[1] < 0.05,
summary(fev1_abs_anova$anova)[[1]]$`Pr(>F)`[1] < 0.05,
summary(ratio_anova$anova)[[1]]$`Pr(>F)`[1] < 0.05
)
)
kable(anova_summary_table, digits = 4,
caption = "Summary of One-Way ANOVA Results (α = 0.05)")
| Variable | F_Statistic | P_Value | Significant |
|---|---|---|---|
| FVC% | 2.7066 | 0.0693 | FALSE |
| FVC Absolute | 0.2633 | 0.7688 | FALSE |
| FEV1% | 4.1131 | 0.0178 | TRUE |
| FEV1 Absolute | 2.2526 | 0.1079 | FALSE |
| FEV1/FVC Ratio | 2.8480 | 0.0604 | FALSE |