#load packages
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.2.1 ✔ readr 2.2.0
## ✔ forcats 1.0.1 ✔ stringr 1.6.0
## ✔ ggplot2 4.0.3 ✔ tibble 3.3.1
## ✔ lubridate 1.9.5 ✔ tidyr 1.3.2
## ✔ purrr 1.2.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(lattice)
function to simulate simple linear regression data
simulateplantgrowth <- function(n = 500,
alpha = 2,
beta1 = 20,
rse = 8,
moisturerange = c(0.1, 5.0)) {
soilmoisture <- runif(n, min = moisturerange[1], max = moisturerange[2])
error <- rnorm(n, mean = 8, sd = rse)
growthrate <- alpha + beta1 * soilmoisture + error
data.frame(
soilmoisture = soilmoisture,
growthrate = growthrate
)
}
#run simulation
set.seed(123)
datasingle <- simulateplantgrowth()
head(datasingle)
## soilmoisture growthrate
## 1 1.5091298 37.17777
## 2 3.9626952 84.75889
## 3 2.1039869 49.32840
## 4 4.4267853 99.25968
## 5 4.7082897 116.95386
## 6 0.3232268 15.75602
loook at data
# Check the structure and variable types
str(datasingle)
## 'data.frame': 500 obs. of 2 variables:
## $ soilmoisture: num 1.51 3.96 2.1 4.43 4.71 ...
## $ growthrate : num 37.2 84.8 49.3 99.3 117 ...
# Check the number of observations and variables
dim(datasingle)
## [1] 500 2
# Display the first six observations
head(datasingle)
## soilmoisture growthrate
## 1 1.5091298 37.17777
## 2 3.9626952 84.75889
## 3 2.1039869 49.32840
## 4 4.4267853 99.25968
## 5 4.7082897 116.95386
## 6 0.3232268 15.75602
# Display variable names
names(datasingle)
## [1] "soilmoisture" "growthrate"
# Summarize the variables
summary(datasingle)
## soilmoisture growthrate
## Min. :0.1023 Min. : 2.07
## 1st Qu.:1.3054 1st Qu.: 35.89
## Median :2.4351 Median : 58.18
## Mean :2.5269 Mean : 60.71
## 3rd Qu.:3.6912 3rd Qu.: 86.04
## Max. :4.9971 Max. :123.89
# Check for missing values
colSums(is.na(datasingle))
## soilmoisture growthrate
## 0 0
# Check the range of each numeric variable
sapply(datasingle, range)
## soilmoisture growthrate
## [1,] 0.1022802 2.069615
## [2,] 4.9970822 123.885300
# Check the distribution of the numeric variables
datasingle %>%
pivot_longer(
cols = everything(),
names_to = "variable",
values_to = "value"
) %>%
ggplot(aes(x = value)) +
geom_histogram(bins = 30, fill = "pink", colour = "black") +
facet_wrap(~variable, scales = "free") +
theme_minimal() +
labs(
title = "Distributions of Simulated Plant Growth Variables",
x = "Value",
y = "Frequency"
)

plot relationship between soil moisture and plant growth
# Create a scatterplot to investigate the relationship
plot(
growthrate ~ soilmoisture,
data = datasingle,
pch = 19,
col = "purple",
xlab = "Soil Moisture",
ylab = "Plant Growth Rate",
main = "Plant Growth Rate vs. Soil Moisture"
)

## Fit linear model
``` r
# Fit a linear regression model
fitsingle <- lm(
growthrate ~ soilmoisture,
data = datasingle
)
# Display the model results
summary(fitsingle)
##
## Call:
## lm(formula = growthrate ~ soilmoisture, data = datasingle)
##
## Residuals:
## Min 1Q Median 3Q Max
## -22.6237 -4.9465 0.2842 5.5494 21.4450
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 9.9927 0.7461 13.39 <2e-16 ***
## soilmoisture 20.0717 0.2586 77.62 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 8.051 on 498 degrees of freedom
## Multiple R-squared: 0.9237, Adjusted R-squared: 0.9235
## F-statistic: 6025 on 1 and 498 DF, p-value: < 2.2e-16
# Extract fitted values and residuals
datasingle <- datasingle %>%
mutate(
fitted = predict(fitsingle),
residuals = resid(fitsingle)
)
# Display the updated data
head(datasingle)
## soilmoisture growthrate fitted residuals
## 1 1.5091298 37.17777 40.28344 -3.1056647
## 2 3.9626952 84.75889 89.53055 -4.7716535
## 3 2.1039869 49.32840 52.22320 -2.8948018
## 4 4.4267853 99.25968 98.84560 0.4140779
## 5 4.7082897 116.95386 104.49586 12.4580048
## 6 0.3232268 15.75602 16.48041 -0.7243912
plot regression line
# Plot the data and fitted regression line
ggplot(datasingle, aes(x = soilmoisture, y = growthrate)) +
geom_point(alpha = 0.6, colour = "pink") +
geom_smooth(method = "lm", se = TRUE, colour = "purple") +
theme_minimal() +
labs(
title = "Linear Regression of Plant Growth on Soil Moisture",
x = "Soil Moisture",
y = "Plant Growth Rate"
)
## `geom_smooth()` using formula = 'y ~ x'

check model asumptions
# Create diagnostic plots for the linear regression
par(mfrow = c(2, 2))
plot(fitsingle)

par(mfrow = c(1, 1))
residuals
# Plot residuals against fitted values
plot(
datasingle$fitted,
datasingle$residuals,
pch = 19,
col = "pink",
xlab = "Fitted Values",
ylab = "Residuals",
main = "Residuals vs. Fitted Values"
)
# Add a horizontal reference line at zero
abline(h = 0, lty = 2, col = "purple")

Test hypothesis
# Test whether soil moisture is significantly associated with growth
summary(fitsingle)
##
## Call:
## lm(formula = growthrate ~ soilmoisture, data = datasingle)
##
## Residuals:
## Min 1Q Median 3Q Max
## -22.6237 -4.9465 0.2842 5.5494 21.4450
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 9.9927 0.7461 13.39 <2e-16 ***
## soilmoisture 20.0717 0.2586 77.62 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 8.051 on 498 degrees of freedom
## Multiple R-squared: 0.9237, Adjusted R-squared: 0.9235
## F-statistic: 6025 on 1 and 498 DF, p-value: < 2.2e-16
# Extract the estimated slope and its p-value
slope <- coef(summary(fitsingle))["soilmoisture", "Estimate"]
pvalue <- coef(summary(fitsingle))["soilmoisture", "Pr(>|t|)"]
# Print the results
cat("Estimated slope:", slope, "\n")
## Estimated slope: 20.07165
cat("P-value:", pvalue, "\n")
## P-value: 2.451417e-280
# Interpret the statistical result
if (pvalue < 0.05) {
print("Soil moisture has a statistically significant relationship with plant growth.")
} else {
print("There is insufficient evidence of a statistically significant relationship.")
}
## [1] "Soil moisture has a statistically significant relationship with plant growth."
conclusion
The simulated data were used to investigate the relationship between
soil moisture and plant growth rate. A scatterplot and linear regression
model were used to examine whether plant growth changes with soil
moisture.
The regression slope estimates the change in growth rate associated
with a one-unit increase in soil moisture. The p-value indicates whether
the observed relationship is statistically significant at the 0.05
significance level. The diagnostic plots help assess whether the linear
regression assumptions are reasonable