Code
library(rstan)
if (!require("bayesplot")) {
install.packages("bayesplot")
library(bayesplot)
}if (!require("ggplot2")) {
install.packages("ggplot2")
library(ggplot2)
}
Sunday funday! First let
The aim is to determine if fasting is not inferior to non-fasting. Noninferiority is typically concluded if the upper limit of the CI is below a predefined margin (here, 4%).
The error bars (CIs) crossing the noninferiority margin suggest that noninferiority cannot be concluded within that subgroup. If the upper limit of the CI is above the noninferiority margin, it indicates that we cannot rule out a potential disadvantage of fasting.
P-value for Interaction: These p-values test whether there is a statistically significant interaction between the treatment effect and the subgroup variable. A significant p-value for interaction would suggest that the treatment effect differs across subgroups.
Conclusion Based on Error Bars: You are 100% correct that CIs cross the noninferiority margin, noninferiority cannot be conclusively demonstrated for that subgroup. This suggests that fasting might not be noninferior in these subgroups based on this criterion alone. This is the whole issue with frequentist sampling – the CI only represent the ‘randomness’ (or size) of the sampling interval, not the inherent uncertainty in the parameter, which under a bayesian construct is ranodm.
P-value for Interaction: The p-value for interaction assesses whether the differences in treatment effects across subgroups are statistically significant. If the p-values are not significant, it suggests that the observed differences between subgroups could be due to chance rather than a true interaction.
Low Statistical Power: Excellent point – Non-significant results in subgroups could indeed be due to low statistical power, meaning the study might not have enough participants in each subgroup to detect a difference if one exists.
To provide a more detailed analysis, we can consider Bayesian methods to estimate the posterior distributions of the treatment effects in each subgroup. This approach can provide a more nuanced understanding of the uncertainty and potential effects.
** Model Setup: Define a Bayesian model for the treatment effect with priors based on existing knowledge or noninformative priors if no prior information is available.
** Data: Use the point estimates and confidence intervals provided in the figure to inform the likelihood function of the Bayesian model.
** Posterior Computation: Use Markov Chain Monte Carlo (MCMC) methods to sample from the posterior distribution of the treatment effects.
** Interpretation: Analyze the posterior distributions to estimate the probability that fasting is noninferior in each subgroup.
** Define the Priors: Choose priors for the treatment effect parameters. For example, you could use normal priors with mean 0 and a large variance to be non-informative.
** Likelihood Function: Define the likelihood based on the observed differences and standard errors.
** MCMC Sampling: Use an MCMC algorithm to sample from the posterior distribution.
library(rstan)
if (!require("bayesplot")) {
install.packages("bayesplot")
library(bayesplot)
}if (!require("ggplot2")) {
install.packages("ggplot2")
library(ggplot2)
}
Prepare the data from the figure. You will need the point estimates and standard errors for each subgroup. For simplicity, let’s assume we have these values in two vectors:
<- c(-2.2, -0.4, -1.9, 0.2, -2.0, -2.4, -1.5, -2.1, 0.6, -6.9, 0.3, -6.5, -0.3, -5.6, 0.1, -5.4, -2.7, -0.8, -2.4, -2.2, -3.2, 0.2, -2.9, 1.6)
effect_estimates <- c(1.5, 10.0, 1.8, 10.3, 2.1, 5.1, 2.4, 5.3, 4.3, 0.7, 4.5, 4.4, 4.0, 4.4, 4.4, 0.6, 1.1, 6.9, 1.3, 0.3, 0.4, 10.4, 0.6, 11.4)
standard_errors
<- list(
data N = length(effect_estimates),
y = effect_estimates,
sigma = standard_errors
)
=readRDS("~/Dropbox/bayesfordave.rds")
fit
# Extract posterior samples
<- extract(fit)
posterior_samples
# Summarize posterior distributions
<- summary(fit)$summary
summary_stats print(summary_stats)
mean se_mean sd 2.5% 25% 50%
theta[1] -2.14813000 0.014401917 1.4835405 -5.038503 -3.103461 -2.1643153
theta[2] -0.25156648 0.074014864 7.2567012 -14.332572 -5.196918 -0.3015761
theta[3] -1.81674406 0.017877043 1.8030185 -5.397254 -3.030210 -1.8322636
theta[4] 0.02714423 0.072654667 7.2329513 -13.806329 -5.020946 -0.0267851
theta[5] -1.92170720 0.021600612 2.0669786 -5.930416 -3.304236 -1.9517246
theta[6] -1.88689133 0.052768720 4.5978333 -10.959172 -4.937647 -1.8969134
theta[7] -1.44921773 0.025408379 2.4272687 -6.168094 -3.129256 -1.4202147
theta[8] -1.69609573 0.049227106 4.6527647 -10.975043 -4.851948 -1.7010115
theta[9] 0.43474114 0.039719254 3.9404745 -7.293749 -2.217262 0.4242291
theta[10] -6.87567236 0.007640060 0.6904785 -8.196983 -7.352874 -6.8692705
theta[11] 0.26552066 0.042530606 4.1921437 -7.882071 -2.535881 0.2526474
theta[12] -5.43783765 0.043636523 3.9560337 -13.338587 -8.063553 -5.3744961
theta[13] -0.21643223 0.035823723 3.5197144 -7.085083 -2.656537 -0.2146551
theta[14] -4.70758544 0.042116091 3.9939337 -12.362733 -7.502649 -4.7375386
theta[15] 0.13688658 0.038836135 4.0986447 -7.857457 -2.642336 0.1426213
theta[16] -5.38429657 0.006100858 0.6040838 -6.551006 -5.788199 -5.3831410
theta[17] -2.67547895 0.011386437 1.1062618 -4.802699 -3.422145 -2.6625104
theta[18] -0.64156994 0.060931920 5.9047475 -11.998640 -4.634306 -0.6703853
theta[19] -2.39433132 0.013303115 1.2611413 -4.913035 -3.198259 -2.3849390
theta[20] -2.19836594 0.003148030 0.2986705 -2.792040 -2.398769 -2.1960413
theta[21] -3.19423813 0.004207331 0.3974801 -3.989931 -3.457734 -3.1950120
theta[22] 0.05062955 0.074288645 7.1412023 -14.027257 -4.731665 0.1111522
theta[23] -2.88688091 0.005771166 0.6058108 -4.077371 -3.282941 -2.8910184
theta[24] 0.72149598 0.079680934 7.3948304 -14.063872 -4.326853 0.7510891
lp__ -13.06252382 0.095624603 3.4428874 -20.990593 -15.148248 -12.7577536
75% 97.5% n_eff Rhat
theta[1] -1.1923712 0.8315832 10611.046 0.9991583
theta[2] 4.6881180 14.1715632 9612.594 0.9992920
theta[3] -0.5908510 1.7573360 10172.062 0.9992540
theta[4] 5.1354045 13.8491265 9910.694 0.9995040
theta[5] -0.5072655 2.1142406 9156.718 0.9993648
theta[6] 1.1878947 7.0047318 7591.950 0.9995094
theta[7] 0.2282088 3.2513323 9126.028 0.9992373
theta[8] 1.5332004 7.4757494 8933.334 0.9993167
theta[9] 3.0333167 8.2659613 9842.261 0.9993534
theta[10] -6.4023909 -5.5421195 8167.833 0.9991477
theta[11] 3.0987824 8.4216576 9715.590 0.9991215
theta[12] -2.7785997 2.3051879 8219.013 0.9992204
theta[13] 2.2069894 6.6778076 9653.247 0.9990769
theta[14] -1.9721810 3.1473549 8993.021 0.9998970
theta[15] 2.9062528 8.1677548 11138.034 0.9991271
theta[16] -4.9716750 -4.1844857 9804.206 0.9991071
theta[17] -1.9253272 -0.5903473 9439.307 0.9991686
theta[18] 3.4402190 10.8804036 9391.024 0.9992591
theta[19] -1.6011580 0.1335143 8987.126 0.9993026
theta[20] -1.9950226 -1.6232681 9001.338 0.9996738
theta[21] -2.9227650 -2.4188498 8925.191 0.9995879
theta[22] 4.7686907 14.1080228 9240.549 0.9995548
theta[23] -2.4889414 -1.6766361 11019.117 0.9993520
theta[24] 5.6555648 15.3319247 8612.864 0.9994452
lp__ -10.5707240 -7.4116084 1296.303 1.0008027
# Trace plot for the first treatment effect
#traceplot(fit, pars = c("theta[1]"))
# Density plots for the treatment effects
mcmc_areas(as.array(fit), pars = paste0("theta[", 1:24, "]"))
# Credible interval plot for the treatment effects
mcmc_intervals(as.array(fit), pars = paste0("theta[", 1:24, "]"))
# Function to visualize posterior distribution and credible intervals
<- function(fit, margin = 4) {
plot_posterior_distributions # Extract posterior samples
<- extract(fit)$theta
posterior_samples
# Calculate credible intervals
<- apply(posterior_samples, 2, function(x) {
credible_intervals quantile(x, probs = c(0.025, 0.5, 0.975))
})
# Convert to data frame for plotting
<- as.data.frame(t(credible_intervals))
df colnames(df) <- c("Lower", "Median", "Upper")
$Subgroup <- 1:nrow(df)
df
# Plot credible intervals
ggplot(df, aes(x = Subgroup, y = Median)) +
geom_point() +
geom_errorbar(aes(ymin = Lower, ymax = Upper), width = 0.2) +
geom_hline(yintercept = margin, linetype = "dashed", color = "red") +
labs(title = "Posterior Distributions and Credible Intervals",
x = "Subgroup",
y = "Effect Estimate",
caption = "Dashed red line represents the noninferiority margin") +
theme_minimal()
}
# Call the function to plot the posterior distributions
plot_posterior_distributions(fit, margin = 4)
Credible Intervals:
The plot shows the 95% credible intervals for the effect estimates. This provides a range of plausible values for each subgroup’s effect estimate, offering a more nuanced understanding of uncertainty.
You can directly see which subgroups have credible intervals that cross the noninferiority margin (dashed red line). If the entire credible interval is below the margin, it suggests that fasting is noninferior for that subgroup. Conversely, if the credible interval crosses or is above the margin, noninferiority cannot be concluded. The point here is that 95% of the distribtuion (the certainty of the random effect) lies in this margin, rather than simply the frequentist interpreation which is that 95 times out of 100 data intervals constructed in this way would contain parameter of interest. We can then direclty as what percentage of the distribtuion is grater than 4 for example, and in the 4th subgroup it’s pretty convincing that a significant chunk is above the red line.
The plot shows the median estimates of the treatment effects, giving you a central tendency measure for each subgroup.
Unlike a p-value, which only tells you if there is a statistically significant difference, this plot allows you to assess noninferiority directly by comparing the credible intervals to the noninferiority margin.
You can visually inspect which subgroups might be at risk of being inferior based on the credible intervals crossing the margin.
A p-value for interaction assesses whether the treatment effect significantly differs across subgroups. It does not provide information about the magnitude or direction of the effects within each subgroup.
The posterior distribution plot gives you the magnitude, direction, and uncertainty of the treatment effects for each subgroup. It allows for a more detailed understanding of the variability and helps in making more informed decisions about noninferiority.
Full Distribution Information:
Bayesian methods provide the entire posterior distribution of the effect estimates, not just a single point estimate or a binary decision based on a p-value.
Credible intervals give you a range of values that are probable given the data and the model, unlike confidence intervals that are often misinterpreted in a frequentist framework. In a frequentist framework, data is random, parameter is fixed, so we’re relaly just offering guarantees about how freuqnetly constructed interval will contain parameter of interest, not how certain (uncertain) we are about the parameter value.
Bayesian analysis can incorporate prior information and provide probabilistic statements about the parameters. For example, you can directly calculate the probability that the effect is within a noninferiority margin.