One-way ANOVA is a statistical method used to compare the means of three or more populations/groups to determine if at least one group mean is statistically different from the others. It’s particularly useful in experimental design to assess the effect of different treatments or conditions on a measured response variable.
The base R installation provides functions like aov() for conducting ANOVA tests and TukeyHSD() for post-hoc analysis, which allows for multiple comparisons after the ANOVA to determine which groups differ.
The aov() function in R is a fundamental tool for conducting Analysis of Variance (ANOVA). It’s part of R’s base packages, meaning it’s readily available without the need for installing additional libraries. ANOVA is a technique used to compare means across two or more groups, and aov() is specifically designed to handle one-way ANOVA, as well as other ANOVA-related tests.
The basic syntax of the aov() function is as follows:
In practice, you’ll often use aov() with just the first two arguments, formula and data, especially for straightforward ANOVA analyses:
The summary() function in R is a generic function used to produce result summaries of various objects in R, such as data frames, model objects (e.g., linear models, ANOVA models), and even basic structures like vectors. The type of summary returned depends on the class of the object for which it is called. This function is highly versatile and one of the most commonly used functions for data analysis in R because it provides a quick, high-level overview of the object, making it easier to understand the data or the model at a glance.
What Does summary() Do?
The actions performed by summary() vary depending on the object’s class:
The summary() function, when applied to an object returned by aov(), provides a concise summary of the ANOVA analysis. It includes:
This summary is crucial for interpreting the results of ANOVA, as it provides the statistical evidence needed to determine whether there are significant differences in the means of the groups defined by the independent variables.
In R, it’s generally a good practice to ensure that categorical variables are explicitly declared as factors before performing Analysis of Variance (ANOVA) or other statistical modeling where the distinction between categorical and continuous variables is important. While R often does a good job of automatically treating character variables as categorical (factors), there are situations where you might need to manually convert them using the factor() function. Here’s why and when converting to factors is important:
Why Convert Categorical Variables to Factors?
Converting an ordinal variable into a factor with specified order:
An effects plot, often used in the context of statistical models, displays the estimated effects of categorical variables (usually represented as factors) on a response variable, allowing for visual interpretation of the model’s findings. In R, ggplot2 can be used for plotting statistical summaries, including the effects of different levels of a factor on a response variable. It helps in understanding how the response changes across different levels of the factor. Here’s how you can create an effects plot using ggplot2.
Assuming you have a dataset data with a response variable response and a factor factorVar, here’s a guide to creating an effects plot.
ggplot(data, aes(x = factorVar, y = response)) +
stat_summary(fun = mean, geom = "point") +
stat_summary(fun = mean, geom = "line", aes(group = 1)) +
ggtitle("Effects Plot of Response by FactorVar")
Post-hoc analysis is a critical step in statistical analysis, particularly after conducting ANOVA (Analysis of Variance) tests. When an ANOVA indicates significant differences between group means, it tells us that not all groups are the same, but it doesn’t specify which groups differ from each other. This is where post-hoc analyses like Tukey’s Honestly Significant Difference (TukeyHSD) test come into play.
Application in R:
After conducting an ANOVA in R, the TukeyHSD() function performs the post-hoc analysis, allowing for an examination of pairwise mean differences with adjusted confidence intervals:
This code conducts a TukeyHSD test and then plots the confidence intervals for the mean differences between groups. The plot visually represents the magnitude of differences and their statistical significance, offering an intuitive understanding of which groups significantly differ from each other.
(Data Set: eduproduct.csv) Evaluation of a New Educational Product. A company designed two versions of a new educational product to improve children’s reading comprehension. They would like to claim that children would acquire better reading comprehension skills utilizing either of the two versions than with the traditional approach. You are helping the company to prepare the marketing material, which will include the results of a study conducted to compare the two versions of the new product with the traditional method. The standard method is called Basal (B), and the two variations of the new method are called DRTA (D) and Strat (S).
Education researchers randomly divided 66 children into three groups of \(22\). Each group was taught by one of the three methods. The response variable is a measure of reading comprehension called Comp that was obtained by a test taken after the instruction was completed.
The study aims to determine which of three educational methods most effectively improves children’s reading comprehension. Through visual and statistical analysis, including ANOVA at a \(\alpha=0.05\) significance level, we will identify any significant differences in efficacy between methods. If significant differences are found, post-hoc analysis will identify which methods stand out. The results will be summarized in a report that interprets the educational impact in straightforward terms, accessible to a general audience.
edu.df <- read.csv("Data/eduproduct.csv", header = TRUE)
# Convert to factor variable
edu.df$GroupName <- factor(edu.df$GroupName)
ggplot(data = edu.df, aes(x = GroupName, y = Comp)) +
stat_summary(fun = mean, geom = "point") +
stat_summary(fun = mean, geom = "line", aes(group = 1)) +
ggtitle("Effects Plot of Comp by GroupName")
The effects plot offers a succinct visualization of the impacts associated with various educational approaches: the traditional Basal (B), and the innovative DRTA (D) and Strat (S) methodologies. Particularly in the context of a one-way ANOVA, this plot becomes helpful for post-hoc analysis following the determination of statistical significance. It facilitates an immediate, clear comparison of the mean outcomes for each educational method. By delineating the relative performance of B, D, and S, the effects plot conveys the practical ranking among these methods based on their average impacts on reading comprehension (B<S<D).
n <- tapply(edu.df$Comp, edu.df$GroupName, length)
xbar <- tapply(edu.df$Comp, edu.df$GroupName, mean)
s <- tapply(edu.df$Comp, edu.df$GroupName, sd)
edu.df$normal.density <- apply(edu.df, 1, function(x){
dnorm(as.numeric(x["Comp"]),
xbar[x["GroupName"]], s[x["GroupName"]])})
summary_table <- data.frame(
GroupName = names(n),
SampleSize = n,
Mean = xbar,
StandardDeviation = s
)
cat("Summary Statistics by Group\n")
print(summary_table, row.names = FALSE)
GroupName | SampleSize | Mean | StandardDeviation |
---|---|---|---|
B | 22 | 41.04545 | 5.635578 |
D | 22 | 46.72727 | 7.388420 |
S | 22 | 44.27273 | 5.766750 |
ggplot(edu.df, aes(x = GroupName, y = Comp)) +
geom_boxplot() +
stat_boxplot(geom = "errorbar") +
stat_summary(fun = mean, colour = "black", geom = "point", size = 3) +
ggtitle("Boxplots of Comp by GroupName")
The side-by-side boxplots greatly overlap. It is difficult to tell if there is any significant differences. However, the innovative DRTA (D) does appear to be greater than traditional Basal (B) as \(Q_1\) of D is above the sample mean of B. However, visual analysis is very subjective. Also, it appears D and S are negatively skewed. No outliers are present any group.
n_bins <- round(max(sqrt(max(n) + 2),5))
ggplot(edu.df, aes(x = Comp)) +
geom_histogram(aes(y = after_stat(density)), bins = n_bins, fill = "grey", col = "black") +
facet_grid(GroupName ~ .) +
geom_density(col = "red", lwd = 1) +
geom_line(aes(y = normal.density), col = "blue", lwd = 1) +
ggtitle("Histograms of Comp by GroupName")
The histograms for groups D and S appear to be slightly negatively skewed but without outliers.
edu.df$intercept <- apply(edu.df, 1, function(x){xbar[x["GroupName"]]})
edu.df$slope <- apply(edu.df, 1, function(x){s[x["GroupName"]]})
#
# (2) Make the QQ plot
#
ggplot(edu.df, aes(sample = Comp)) +
stat_qq() +
facet_grid(GroupName ~ .) +
geom_abline(data = edu.df, aes(intercept = intercept, slope = slope)) +
ggtitle("QQ Plots of Comp by GroupName")
The QQ-plots for groups D and S also demonstrate a negative skewed.
## Df Sum Sq Mean Sq F value Pr(>F)
## GroupName 2 357.3 178.65 4.481 0.0152 *
## Residuals 63 2511.7 39.87
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Step 1: Define parameters - \(\mu_{\textbf B}\) is the population mean Comp score for the Basal method (control). - \(\mu_{\textbf D}\) is the population mean Comp score for the DRTA method. - \(\mu_{\textbf S}\) is the population mean Comp score for the Strat method.
Step 2: State the hypotheses - \(H_0\): \(\mu_{\textbf B}=\mu_{\textbf D}=\mu_{\textbf S}\) - \(H_a\): at least two \(\mu_i\)’s are different.
Step 3: Find the test statistic, p-value, report degrees of freedom
Step 4: Conclusion:
Since \(p\)-value\(=0.0152 < 0.05=\alpha\), we should reject \(H_0\)
The data provides evidence (\(p\)-value \(=0.0152\)) to the claim that the population mean values of at least one of the education methods is different from the rest.
The ANOVA test indicated a difference. Keep in mind that the results of the hypothesis test are more objective than the subjective analysis of the plots. However, you should always look at the plots to get a feel of the data before you do the inference.
## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov(formula = Comp ~ GroupName, data = edu.df)
##
## $GroupName
## diff lwr upr p adj
## D-B 5.681818 1.112137 10.251499 0.0111135
## S-B 3.227273 -1.342408 7.796953 0.2149995
## S-D -2.454545 -7.024226 2.115135 0.4064363
# Tukey critical Value used for confidence interval (This could be used with the MSE for manual calculations)
qtukey(p = 0.05,nmeans = 3, df = 63, lower.tail = FALSE)/sqrt(2)
## [1] 2.400326
There are two ways to determine which pairs are significant and which are not. 1. Check whether \(0\) is in the interval (lwr, upr) if it is than it is not significant. 2. Check whether the p adj is smaller than the significance level. Note that you might not have this information on the exams.
In this case, we have statistical evidence that D and B are different, but we do not have evidence that B is different from S nor that D is different from S. Also notice that in the above plot the confidence interval for D-B does not overlap with \(0\) and therefore they are significant.
The following is the graphical representation you must construct this by hand (unless you want to program R to do this by yourself). Remember that you need to include the means in ascending or descending order.