In this chapter, we will practice four statistical analyses:
# Load required packages
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(ggplot2)
library(ggfortify)
# Import Chapter 5 datasets
lady <- read.csv("ladybirds_morph_colour.csv")
ozone <- read.csv("ozone.csv")
plant_gr <- read.csv("plant.growth.rate.csv")
daphnia <- read.csv("Daphniagrowth.csv")
# Check datasets
str(lady)
## 'data.frame': 20 obs. of 4 variables:
## $ Habitat : chr "Rural" "Rural" "Rural" "Rural" ...
## $ Site : chr "R1" "R2" "R3" "R4" ...
## $ morph_colour: chr "black" "black" "black" "black" ...
## $ number : int 10 3 4 7 6 15 18 9 12 16 ...
str(ozone)
## 'data.frame': 20 obs. of 3 variables:
## $ Ozone : num 61.7 64 72.4 56.8 52.4 44.8 70.4 67.6 68.8 53.7 ...
## $ Garden.location: chr "West" "West" "West" "West" ...
## $ Garden.ID : chr "G1" "G2" "G3" "G4" ...
str(plant_gr)
## 'data.frame': 50 obs. of 2 variables:
## $ soil.moisture.content: num 0.47 0.541 1.698 0.826 0.857 ...
## $ plant.growth.rate : num 21.3 27 39 30.2 37.1 ...
str(daphnia)
## 'data.frame': 40 obs. of 3 variables:
## $ parasite : chr "control" "control" "control" "control" ...
## $ rep : int 1 2 3 4 5 6 7 8 9 10 ...
## $ growth.rate: num 1.07 1.27 1.32 1.08 1.2 ...
library(dplyr)
totals <- lady %>%
group_by(Habitat, morph_colour) %>%
summarise(total.number = sum(number), .groups = "drop")
totals
## # A tibble: 4 × 3
## Habitat morph_colour total.number
## <chr> <chr> <int>
## 1 Industrial black 115
## 2 Industrial red 85
## 3 Rural black 30
## 4 Rural red 70
library(ggplot2)
ggplot(totals, aes(x = Habitat,
y = total.number,
fill = morph_colour)) +
geom_bar(stat = "identity", position = "dodge")
ggplot(totals, aes(x = Habitat,
y = total.number,
fill = morph_colour)) +
geom_bar(stat = "identity", position = "dodge") +
scale_fill_manual(values = c(black = "black",
red = "red"))
Null Hypothesis (H0): There is no association between ladybird colour and habitat.
Alternative Hypothesis (H1): There is an association between ladybird colour and habitat.
Interpretation:
The graph shows that black ladybirds are relatively more common in industrial habitats, while red ladybirds are relatively more common in rural habitats.
This suggests a possible association between ladybird colour and habitat.
We expect to reject the null hypothesis, but a Chi-square test is needed to evaluate the statistical evidence. ### 5.2.6 Chi-square Test
lady.mat <- xtabs(number ~ Habitat + morph_colour,
data = lady)
lady.mat
## morph_colour
## Habitat black red
## Industrial 115 85
## Rural 30 70
lady.chi <- chisq.test(lady.mat)
lady.chi
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: lady.mat
## X-squared = 19.103, df = 1, p-value = 1.239e-05
names(lady.chi)
## [1] "statistic" "parameter" "p.value" "method" "data.name" "observed"
## [7] "expected" "residuals" "stdres"
lady.chi$observed
## morph_colour
## Habitat black red
## Industrial 115 85
## Rural 30 70
lady.chi$expected
## morph_colour
## Habitat black red
## Industrial 96.66667 103.33333
## Rural 48.33333 51.66667
Statistical Results:
A Chi-square contingency table analysis was performed to examine the association between ladybird colour morph and habitat type.
The results showed a statistically significant association between ladybird colour and habitat (χ² = 19.103, df = 1, p < 0.001).
Black ladybirds were relatively more common in industrial habitats (57.5%), whereas red ladybirds were relatively more common in rural habitats (70%).
Conclusion:
We reject the null hypothesis (H0) and conclude that ladybird colour morph is significantly associated with habitat type. ## 5.3 Two-sample t-test
library(ggplot2)
ggplot(ozone, aes(x = Ozone)) +
geom_histogram(binwidth = 10) +
facet_wrap(~ Garden.location, ncol = 1) +
theme_bw()
### 5.3.3 Performing the Two-sample t-test
t.test(Ozone ~ Garden.location, data = ozone)
##
## Welch Two Sample t-test
##
## data: Ozone by Garden.location
## t = 4.2363, df = 17.656, p-value = 0.0005159
## alternative hypothesis: true difference in means between group East and group West is not equal to 0
## 95 percent confidence interval:
## 8.094171 24.065829
## sample estimates:
## mean in group East mean in group West
## 77.34 61.26
library(ggplot2)
ggplot(plant_gr,
aes(x = soil.moisture.content,
y = plant.growth.rate)) +
geom_point() +
ylab("Plant Growth Rate (mm/week)") +
theme_bw()
# Fit the linear regression model
model_pgr <- lm(plant.growth.rate ~ soil.moisture.content,
data = plant_gr)
# Diagnostic plots
library(ggfortify)
autoplot(model_pgr, smooth.colour = NA)
## Warning: `fortify(<lm>)` was deprecated in ggplot2 4.0.0.
## ℹ Please use `broom::augment(<lm>)` instead.
## ℹ The deprecated feature was likely used in the ggfortify package.
## Please report the issue at <https://github.com/sinhrks/ggfortify/issues>.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## ℹ The deprecated feature was likely used in the ggfortify package.
## Please report the issue at <https://github.com/sinhrks/ggfortify/issues>.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning: Removed 50 rows containing missing values or values outside the scale range
## (`geom_line()`).
## Removed 50 rows containing missing values or values outside the scale range
## (`geom_line()`).
## Removed 50 rows containing missing values or values outside the scale range
## (`geom_line()`).
### 5.5.5 Linear Regression Results
# ANOVA table
anova(model_pgr)
## Analysis of Variance Table
##
## Response: plant.growth.rate
## Df Sum Sq Mean Sq F value Pr(>F)
## soil.moisture.content 1 2521.15 2521.15 156.08 < 2.2e-16 ***
## Residuals 48 775.35 16.15
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Regression model summary
summary(model_pgr)
##
## Call:
## lm(formula = plant.growth.rate ~ soil.moisture.content, data = plant_gr)
##
## Residuals:
## Min 1Q Median 3Q Max
## -8.9089 -3.0747 0.2261 2.6567 8.9406
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 19.348 1.283 15.08 <2e-16 ***
## soil.moisture.content 12.750 1.021 12.49 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 4.019 on 48 degrees of freedom
## Multiple R-squared: 0.7648, Adjusted R-squared: 0.7599
## F-statistic: 156.1 on 1 and 48 DF, p-value: < 2.2e-16
ggplot(plant_gr, aes(x = soil.moisture.content,
y = plant.growth.rate)) +
geom_point() +
geom_smooth(method = "lm") +
ylab("Plant Growth Rate (mm/week)") +
theme_bw()
## `geom_smooth()` using formula = 'y ~ x'
### 5.5.7 Linear Regression Summary
A simple linear regression was performed to examine the relationship between soil moisture content and plant growth rate.
Results:
library(ggplot2)
ggplot(daphnia, aes(x = parasite, y = growth.rate)) +
geom_boxplot() +
theme_bw() +
coord_flip()
### 5.6.2 Constructing the ANOVA Model
# Fit the one-way ANOVA model
model_grow <- lm(growth.rate ~ parasite, data = daphnia)
# Check model assumptions
library(ggfortify)
autoplot(model_grow, smooth.colour = NA)
## Warning: Removed 40 rows containing missing values or values outside the scale range
## (`geom_line()`).
## Removed 40 rows containing missing values or values outside the scale range
## (`geom_line()`).
### 5.6.4 One-way ANOVA Results
# ANOVA table
anova(model_grow)
## Analysis of Variance Table
##
## Response: growth.rate
## Df Sum Sq Mean Sq F value Pr(>F)
## parasite 3 3.1379 1.04597 32.325 2.571e-10 ***
## Residuals 36 1.1649 0.03236
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Model summary and treatment contrasts
summary(model_grow)
##
## Call:
## lm(formula = growth.rate ~ parasite, data = daphnia)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.41930 -0.09696 0.01408 0.12267 0.31790
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.21391 0.05688 21.340 < 2e-16 ***
## parasiteMetschnikowia bicuspidata -0.41275 0.08045 -5.131 1.01e-05 ***
## parasitePansporella perplexa -0.13755 0.08045 -1.710 0.0959 .
## parasitePasteuria ramosa -0.73171 0.08045 -9.096 7.34e-11 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.1799 on 36 degrees of freedom
## Multiple R-squared: 0.7293, Adjusted R-squared: 0.7067
## F-statistic: 32.33 on 3 and 36 DF, p-value: 2.571e-10
library(dplyr)
# Calculate mean growth rate for each treatment
sumDat <- daphnia %>%
group_by(parasite) %>%
summarise(meanGR = mean(growth.rate))
# Display group means
sumDat
## # A tibble: 4 × 2
## parasite meanGR
## <chr> <dbl>
## 1 Metschnikowia bicuspidata 0.801
## 2 Pansporella perplexa 1.08
## 3 Pasteuria ramosa 0.482
## 4 control 1.21
ggplot(daphnia, aes(x = parasite, y = growth.rate)) +
geom_point(position = position_jitter(width = 0.1),
alpha = 0.6) +
geom_point(data = sumDat,
aes(x = parasite, y = meanGR),
inherit.aes = FALSE,
shape = 23, size = 4, fill = "red") +
coord_flip() +
theme_bw() +
labs(x = "Parasite",
y = "Growth Rate")
## 5.7 Chapter Summary
Four statistical methods were applied using R:
Data visualization, model fitting, diagnostic plots, and statistical summaries were performed using R, ggplot2, dplyr, and ggfortify.