Skip to content

R - 均值、中位数与众数

R - 描述性统计:均值、中位数和众数

Section titled “R - 描述性统计:均值、中位数和众数”

描述性统计用于总结和描述数据集的主要特征。最常见的集中趋势度量是均值、中位数和众数。在 R 语言中,这些通常在使用 tidyverse 的现代数据分析工作流程中,通过内置函数轻松计算。

均值是所有值之和除以值的数量。它对异常值(极高或极低的值)敏感。在 R 中使用 mean() 函数。

mean(x, trim = 0, na.rm = FALSE, ...)
  • x:一个数值向量。
  • trim:在计算均值之前,从排序向量的两端修剪的观测值比例(从 0 到 0.5)。这使得均值对异常值更具鲁棒性。
  • na.rm:一个逻辑值(TRUE 或 FALSE)。如果为 TRUE,则在计算前移除任何 NA(缺失)值。这是一个关键且常用的参数。
# 创建一个分数样本向量
scores <- c(88, 92, 85, 95, 88, 76, 54, 98)
# 计算均值
mean_score <- mean(scores)
print(mean_score)
# [1] 84.5

默认情况下,如果向量中任何值为 NA,mean() 将返回 NA。您必须明确告诉它忽略这些值。

# 带有缺失值的向量
scores_with_na <- c(88, 92, NA, 95, 88, 76, 54, 98)
# 这将返回 NA
mean(scores_with_na)
# [1] NA
# 这将正确计算可用数字的均值
mean(scores_with_na, na.rm = TRUE)
# [1] 86.57143

中位数是已按升序排序的数据集中的中间值。如果数据集包含偶数个值,则中位数是两个中间值的平均值。中位数对异常值具有鲁棒性。

median(x, na.rm = FALSE)
# 使用我们原始的分数向量
# 排序后的分数: 54, 76, 85, 88, 88, 92, 95, 98
# 中间值是 88 和 88, 因此中位数是 88。
median_score <- median(scores)
print(median_score)
# [1] 88
# 带有异常值的向量
salaries <- c(50000, 52000, 55000, 60000, 1500000)
mean(salaries) # [1] 343400 (受异常值严重影响)
median(salaries) # [1] 55000 (更好地代表了“典型”薪水)

最佳实践:当您的数据存在异常值或偏斜时,中位数通常比均值更能代表集中趋势。

众数是在数据集中出现最频繁的值。一个数据集可以有一个众数、多个众数或根本没有众数。R 没有内置的标准众数函数,但它很容易计算。

一种常见的方法是创建一个频率表并找到计数最高的值。这是一个实现此功能的简单函数。

# 一个计算众数的函数
get_mode <- function(v) {
# 统计每个唯一值的频率
freq_table <- table(v)
# 找到最大频率的名称
names(freq_table)[which.max(freq_table)]
}
# 数字示例
# 数字 88 出现了两次
scores <- c(88, 92, 85, 95, 88, 76, 54, 98)
mode_result <- get_mode(scores)
print(mode_result)
# [1] "88" (注意:输出是字符类型,如果需要可使用 as.numeric() 转换)
# 字符示例
colors <- c("blue", "red", "blue", "green", "blue", "red")
mode_color <- get_mode(colors)
print(mode_color)
# [1] "blue"

Tidyverse 工作流程中的描述性统计

Section titled “Tidyverse 工作流程中的描述性统计”

在现代数据分析中,您很少在独立的向量上计算这些统计量。相反,您会使用 dplyr::summarise() 为数据框中的变量计算它们。这是一种非常强大且易读的模式。

library(tidyverse)
# 使用内置的 'iris' 数据集
data(iris)
# 为每个物种计算 Sepal.Length 的描述性统计量
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), # 标准差
min_sepal_length = min(Sepal.Length),
max_sepal_length = max(Sepal.Length),
count = n() # 观测值计数
)
print(iris_summary)

这将生成一个整洁的汇总表,非常适合报告和进一步分析。

# 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