knitr::opts_chunk$set(echo = TRUE, message = FALSE, warning = FALSE)

# Install once if needed:
# install.packages(c("agricolae","gt","broom","corrplot","car"))

library(agricolae)  # sweetpotato and corn datasets
library(gt)          # nice tables
library(dplyr)        # select() used with tidy() output
library(broom)          # tidy() turns test/model output into a data frame
library(corrplot)         # correlogram
library(car)                # vif() for multicollinearity check

1 The Datasets

Module 6 uses sweetpotato (yield by virus treatment, 12 plots).

Module 7 uses corn, a different built-in agricolae dataset — a completely randomized design comparing 4 corn-growing methods. It has 34 plots and, importantly, two numeric variables recorded on the same plots:

  • method — growing method (1 to 4)
  • observation — yield per plot
  • rx — a second numeric measurement taken on the same plot

Having two numeric variables on the same units is what lets us do real (not simulated) correlation, regression, and paired testing in Module 7.

data(sweetpotato)
data(corn)

str(sweetpotato)
## 'data.frame':    12 obs. of  2 variables:
##  $ virus: Factor w/ 4 levels "cc","fc","ff",..: 1 1 1 2 2 2 3 3 3 4 ...
##  $ yield: num  28.5 21.7 23 14.9 10.6 13.1 41.8 39.2 28 38.2 ...
str(corn)
## 'data.frame':    34 obs. of  3 variables:
##  $ method     : int  1 1 1 1 1 1 1 1 1 2 ...
##  $ observation: int  83 91 94 89 89 96 91 92 90 91 ...
##  $ rx         : num  11 23 28.5 17 17 31.5 23 26 19.5 23 ...

2 MODULE 6: Descriptive Statistics

Descriptive statistics simply describe the data — count it, find its center, find its spread.

2.1 Count and Frequency Table

Definition. A frequency table shows how many times each category appears.

What it’s for. The first step in looking at any categorical variable — here, how many plots got each virus treatment.

Note: Works for any categorical variable.

freq <- table(sweetpotato$virus)

freq_df <- as.data.frame(freq)
names(freq_df) <- c("Virus", "Frequency")

gt(freq_df) |>
  tab_header(title = "Frequency of Virus Treatments")
Frequency of Virus Treatments
Virus Frequency
cc 3
fc 3
ff 3
oo 3

Interpretation. Each row shows how many plots received that virus treatment. Each treatment appears 3 times here — a balanced design.

2.2 Percentage Table

Definition. Turns each frequency into a percentage of the total.

What it’s for. Easier to compare groups on a common 0-100% scale.

virus_counts <- table(sweetpotato$virus)

pct_df <- data.frame(
  Virus   = names(virus_counts),
  Percent = round(virus_counts / sum(virus_counts) * 100, 2)
)

gt(pct_df) |>
  tab_header(title = "Percentage of Plots per Virus Treatment")
Percentage of Plots per Virus Treatment
Virus Percent.Var1 Percent.Freq
cc cc 25
fc fc 25
ff ff 25
oo oo 25

Interpretation. With 4 equal-sized groups, each should be about 25%.

2.3 Min, Max, and Range

Definition.

  • Minimum — smallest value
  • Maximum — largest value
  • Range — Maximum minus Minimum

What it’s for. A quick first look at the spread of the data.

Note. Sensitive to outlier.

yield_min   <- min(sweetpotato$yield)
yield_max   <- max(sweetpotato$yield)
yield_range <- yield_max - yield_min

result1 <- data.frame(
  Statistic = c("Minimum", "Maximum", "Range"),
  Value = c(yield_min, yield_max, yield_range)
)

gt(result1) |>
  tab_header(title = "Min, Max, and Range of Yield")
Min, Max, and Range of Yield
Statistic Value
Minimum 10.6
Maximum 41.8
Range 31.2

Interpretation. Range shows how far apart the smallest and largest yields are. A large range means high variability in the data.

2.4 Measures of Central Tendency

Definition.

  • Mean — the average
  • Median — the middle value
  • Mode — the most frequent value

What it’s for. Finding one “typical” value to represent the data.

Note. Mean works best when data is not heavily skewed.

For the mode function, there is no native function for finding the mode. So we formulated a function for this example.

get_mode <- function(x) {
  ux <- unique(x)
  ux[which.max(tabulate(match(x, ux)))]
}
yield_mean   <- mean(sweetpotato$yield)
yield_median <- median(sweetpotato$yield)
yield_mode   <- get_mode(sweetpotato$yield)

result2 <- data.frame(
  Statistic = c("Mean", "Median", "Mode"),
  Value = c(yield_mean, yield_median, yield_mode)
)

gt(result2) |>
  fmt_number(columns = Value, decimals = 2) |>
  tab_header(title = "Central Tendency of Yield")
Central Tendency of Yield
Statistic Value
Mean 27.62
Median 28.25
Mode 28.50

By treatment group:

sweetpotato |> 
  group_by(virus) |> 
  summarise(mean= mean(yield, na.rm =TRUE),
            median = median (yield, na.rm=TRUE)) |> 
  gt() |> 
  fmt_number(decimals = 2) |> 
  tab_header(title = "Mean and Median Yield by Virus Treatment")
Mean and Median Yield by Virus Treatment
virus mean median
cc 24.40 23.00
fc 12.87 13.10
ff 36.33 39.20
oo 36.90 38.20

Interpretation. If Mean and Median are close, the data is fairly symmetric. A treatment with a much higher mean than the others is producing more yield on average.

2.5 Measures of Variability

Definition.

  • Variance — average squared distance from the mean
  • Standard Deviation (SD) — square root of variance
  • Coefficient of Variation (CV) — SD as a percent of the mean
  • Interquartile Range (IQR) — spread of the middle 50% of the data

What it’s for. Tells you how spread out (consistent vs. erratic) the data is.

Note. Variance/SD assume numeric interval/ratio data. CV needs a meaningful non-zero mean.

yield <- sweetpotato$yield

result3 <- data.frame(
  Statistic = c("Variance", "Standard Deviation", "CV (%)", "IQR"),
  Value = c(var(yield), sd(yield), sd(yield) / mean(yield) * 100,
    IQR(yield)
  )
)

gt(result3) |>
  fmt_number(columns = Value, decimals = 2) |>
  tab_header(title = "Variability of Yield")
Variability of Yield
Statistic Value
Variance 122.74
Standard Deviation 11.08
CV (%) 40.10
IQR 18.45

By treatment group:

sweetpotato |> 
  group_by(virus) |> 
  summarise("standard deviation" = sd(yield, na.rm =TRUE)) |> 
  gt() |> 
  fmt_number(decimals = 2) |> 
  tab_header(title = "Standard Deviation of Yield by Virus Treatment")
Standard Deviation of Yield by Virus Treatment
virus standard deviation
cc 3.61
fc 2.16
ff 7.33
oo 4.30