Skip to content

R - Mean, Median & Mode

R - Descriptive Statistics: Mean, Median, and Mode

Section titled “R - Descriptive Statistics: Mean, Median, and Mode”

Descriptive statistics are used to summarize and describe the main features of a dataset. The most common measures of central tendency are the mean, median, and mode. In R, these are easily calculated using built-in functions, often within a modern data analysis workflow using the tidyverse.

The mean is the sum of all values divided by the number of values. It’s sensitive to outliers (extremely high or low values). The function mean() is used in R.

mean(x, trim = 0, na.rm = FALSE, ...)
  • x: A numeric vector.
  • trim: The fraction (from 0 to 0.5) of observations to be trimmed from each end of the sorted vector before the mean is computed. This makes the mean more robust to outliers.
  • na.rm: A logical value (TRUE or FALSE). If TRUE, any NA (missing) values are removed before calculation. This is a crucial and commonly used argument.
# Create a sample vector of scores
scores <- c(88, 92, 85, 95, 88, 76, 54, 98)
# Calculate the mean
mean_score <- mean(scores)
print(mean_score)
# [1] 84.5

By default, mean() will return NA if any value in the vector is NA. You must explicitly tell it to ignore them.

# Vector with a missing value
scores_with_na <- c(88, 92, NA, 95, 88, 76, 54, 98)
# This will return NA
mean(scores_with_na)
# [1] NA
# This will correctly calculate the mean of the available numbers
mean(scores_with_na, na.rm = TRUE)
# [1] 86.57143

The median is the middle value of a dataset that has been sorted in ascending order. If the dataset has an even number of values, the median is the average of the two middle values. The median is robust to outliers.

median(x, na.rm = FALSE)
# Use our original scores vector
# Sorted scores: 54, 76, 85, 88, 88, 92, 95, 98
# Middle values are 88 and 88, so the median is 88.
median_score <- median(scores)
print(median_score)
# [1] 88
# A vector with an outlier
salaries <- c(50000, 52000, 55000, 60000, 1500000)
mean(salaries) # [1] 343400 (heavily skewed by the outlier)
median(salaries) # [1] 55000 (a much better representation of the 'typical' salary)

Best Practice: When your data has outliers or is skewed, the median is often a more representative measure of central tendency than the mean.

The mode is the value that appears most frequently in a dataset. A dataset can have one mode, more than one mode, or no mode at all. R does not have a built-in standard function for the mode, but it’s easy to calculate.

A common approach is to create a frequency table and find the value with the highest count. Here is a simple function to do that.

# A function to calculate the mode
get_mode <- function(v) {
# Tally the frequencies of each unique value
freq_table <- table(v)
# Find the name of the maximum frequency
names(freq_table)[which.max(freq_table)]
}
# Example with numbers
# The number 88 appears twice
scores <- c(88, 92, 85, 95, 88, 76, 54, 98)
mode_result <- get_mode(scores)
print(mode_result)
# [1] "88" (Note: output is a character, convert with as.numeric() if needed)
# Example with characters
colors <- c("blue", "red", "blue", "green", "blue", "red")
mode_color <- get_mode(colors)
print(mode_color)
# [1] "blue"

Descriptive Statistics in a Tidyverse Workflow

Section titled “Descriptive Statistics in a Tidyverse Workflow”

In modern data analysis, you rarely calculate these statistics on loose vectors. Instead, you use dplyr::summarise() to compute them for variables in a data frame. This is a highly powerful and readable pattern.

library(tidyverse)
# Use the built-in 'iris' dataset
data(iris)
# Calculate descriptive statistics for Sepal.Length for each species
iris_summary <- iris %>%
group_by(Species) %>%
summarise(
mean_sepal_length = mean(Sepal.Length, na.rm = TRUE),
median_sepal_length = median(Sepal.Length, na.rm = TRUE),
sd_sepal_length = sd(Sepal.Length, na.rm = TRUE), # Standard Deviation
min_sepal_length = min(Sepal.Length),
max_sepal_length = max(Sepal.Length),
count = n() # Count of observations
)
print(iris_summary)

This produces a clean summary table, ideal for reports and further analysis.

# A tibble: 3 × 7
Species mean_sepal_length median_sepal_length sd_sepal_length min_sepal_length max_sepal_length count
<fct> <dbl> <dbl> <dbl> <dbl> <dbl> <int>
1 setosa 5.01 5 0.352 4.3 5.8 50
2 versicolor 5.94 5.9 0.516 4.9 7 50
3 virginica 6.59 6.5 0.636 4.9 7.9 50