R语言数据计算与分组统计
一、数据计算
1. 求和 sum()
r
# 创建一个数值向量
scores <- c(85, 90, 78, 92, 88)
# 计算所有元素的总和
total <- sum(scores) # sum()函数将向量中所有数值相加
print(total) # 输出: 433
2. 求均值 mean()
r
# 计算平均值
average <- mean(scores) # mean()计算算术平均数
print(average) # 输出: 86.6
3. 求最大值 max()
r
# 找出最大值
max_score <- max(scores) # max()返回向量中的最大值
print(max_score) # 输出: 92
4. 求最小值 min()
r
# 找出最小值
min_score <- min(scores) # min()返回向量中的最小值
print(min_score) # 输出: 78
5. 求中位数 median()
r
# 计算中位数(排序后中间位置的值)
median_score <- median(scores) # median()计算中位数
print(median_score) # 输出: 88
6. 求众数(自定义函数)
r
# R基础包没有内置众数函数,需要自定义
get_mode <- function(x) {
# 计算每个唯一值出现的频率
freq_table <- table(x) # table()创建频数表
# 找出最大频数对应的值(可能有多个)
mode_value <- names(freq_table)[freq_table == max(freq_table)]
return(mode_value)
}
# 测试数据(包含重复值)
test_scores <- c(85, 90, 85, 92, 85, 88)
mode_result <- get_mode(test_scores)
print(mode_result) # 输出: "85"
7. 求方差 var()
r
# 计算样本方差(除以n-1)
variance <- var(scores) # var()计算样本方差
print(variance) # 输出: 31.3
# 计算总体方差(除以n)
pop_variance <- var(scores) * (length(scores)-1)/length(scores)
print(pop_variance) # 输出: 25.04
8. 求标准差 sd()
r
# 计算样本标准差(方差的平方根)
std_dev <- sd(scores) # sd()计算样本标准差
print(std_dev) # 输出: 5.59464
9. 求分位数 quantile()
r
# 计算不同分位数的值
# 默认计算0%、25%、50%、75%、100%分位数
quantiles <- quantile(scores)
print(quantiles)
# 输出:
# 0% 25% 50% 75% 100%
# 78.0 86.5 88.0 90.5 92.0
# 计算自定义分位数(如10%、30%、60%、90%)
custom_quantiles <- quantile(scores, probs = c(0.1, 0.3, 0.6, 0.9))
print(custom_quantiles)
10. 求多个计算结果 summary()
r
# summary()一次性计算:最小值、1/4分位数、中位数、均值、3/4分位数、最大值
summary_stats <- summary(scores)
print(summary_stats)
# 输出:
# Min. 1st Qu. Median Mean 3rd Qu. Max.
# 78.0 86.5 88.0 86.6 90.5 92.0
二、数据分组统计
准备工作:创建示例数据框
r
# 创建一个学生成绩数据框,用于演示分组统计
students <- data.frame(
class = c("A", "A", "B", "B", "C", "C", "A", "B", "C"), # 班级
gender = c("M", "F", "M", "F", "M", "F", "M", "F", "M"), # 性别
score = c(85, 90, 78, 88, 92, 86, 89, 84, 91), # 成绩
age = c(18, 17, 18, 19, 18, 17, 19, 18, 18) # 年龄
)
print(students)
1. apply() 函数(用于矩阵/数据框的行或列)
r
# 创建一个矩阵用于演示
score_matrix <- matrix(c(85, 90, 78, 92, 88, 84), nrow = 3, ncol = 2)
colnames(score_matrix) <- c("Math", "English")
rownames(score_matrix) <- c("Student1", "Student2", "Student3")
print(score_matrix)
# apply(X, MARGIN, FUN, ...)
# X: 要处理的矩阵或数据框
# MARGIN: 1表示行,2表示列
# FUN: 要应用的函数
# 按行计算每行的平均值(MARGIN=1)
row_mean <- apply(score_matrix, 1, mean) # 1表示对每一行应用mean函数
print(row_mean)
# 按列计算每列的总和(MARGIN=2)
col_sum <- apply(score_matrix, 2, sum) # 2表示对每一列应用sum函数
print(col_sum)
# 按列计算标准差
col_sd <- apply(score_matrix, 2, sd)
print(col_sd)
2. lapply() 函数(对列表应用函数,返回列表)
r
# 创建一个包含多个向量的列表
score_list <- list(
class_A = c(85, 90, 89),
class_B = c(78, 88, 84),
class_C = c(92, 86, 91)
)
# lapply()对列表的每个元素应用函数,返回列表
# 计算每个班级的平均分
mean_list <- lapply(score_list, mean) # 对列表每个元素计算均值
print(mean_list)
# 计算每个班级的最高分
max_list <- lapply(score_list, max)
print(max_list)
3. sapply() 函数(简化结果,尽量返回向量或矩阵)
r
# sapply()是lapply()的简化版本,结果更简洁
# 计算每个班级的平均分(返回向量)
mean_vector <- sapply(score_list, mean) # 返回命名的数值向量
print(mean_vector)
print(class(mean_vector)) # 查看结果类型:"numeric"
# 计算多个统计量(返回矩阵)
multiple_stats <- sapply(score_list, function(x) {
c(mean = mean(x), sd = sd(x), max = max(x))
})
print(multiple_stats)
4. tapply() 函数(按因子分组计算)
r
# tapply(X, INDEX, FUN, ...)
# X: 要计算的数值向量
# INDEX: 因子或因子列表(分组依据)
# FUN: 要应用的函数
# 按班级(class)分组计算平均分
class_mean <- tapply(students$score, students$class, mean)
print(class_mean)
# 输出:
# A B C
# 88.0000 83.3333 89.6667
# 按性别分组计算最高分
gender_max <- tapply(students$score, students$gender, max)
print(gender_max)
# 输出:
# F M
# 90 92
# 按班级和性别两个因素分组(返回矩阵)
class_gender_mean <- tapply(students$score,
list(students$class, students$gender),
mean)
print(class_gender_mean)
# 输出:
# F M
# A 90.0 87
# B 88.0 81
# C 86.0 NA (C班没有男生?检查:C班只有91分的是男生)
5. 分组统计函数 aggregate()
r
# aggregate()是更易于使用的分组统计函数
# 基本用法:按单个变量分组
# aggregate(待计算列 ~ 分组列, 数据, 函数)
class_agg <- aggregate(score ~ class, data = students, FUN = mean)
print(class_agg)
# 输出:
# class score
# 1 A 88.00000
# 2 B 83.33333
# 3 C 89.66667
# 按多个变量分组
# 使用cbind()指定多列,或使用点号.
multi_agg <- aggregate(cbind(score, age) ~ class + gender,
data = students,
FUN = mean)
print(multi_agg)
# 使用.表示所有其他列分组(不推荐有太多列时使用)
# aggregate(. ~ class, data = students, FUN = mean)
# 使用多个函数的结果(需要自定义)
agg_with_multiple <- aggregate(score ~ class,
data = students,
FUN = function(x) c(mean = mean(x), sd = sd(x)))
print(agg_with_multiple)
6. 分组函数 group_by()(来自dplyr包)
r
# 首先安装并加载dplyr包
# install.packages("dplyr") # 如果未安装,取消注释运行
library(dplyr) # 加载dplyr包
# group_by()配合summarise()实现分组统计
# 使用管道操作符 %>% 使代码更易读
# 按班级分组,计算平均分和标准差
grouped_result <- students %>%
group_by(class) %>% # 按class列分组
summarise( # 对每组计算汇总统计
count = n(), # n()计算每组行数
mean_score = mean(score), # 平均分
sd_score = sd(score), # 标准差
max_score = max(score), # 最高分
min_score = min(score) # 最低分
)
print(grouped_result)
# 按班级和性别分组
grouped_multi <- students %>%
group_by(class, gender) %>% # 按两个变量分组
summarise(
avg_score = mean(score),
avg_age = mean(age),
total_students = n()
)
print(grouped_multi)
# 使用mutate()添加分组后的计算列
students_with_group_mean <- students %>%
group_by(class) %>%
mutate(
class_mean = mean(score), # 添加该生所在班级的平均分
deviation = score - class_mean # 与班级平均分的差值
)
print(students_with_group_mean)
三、数据透视表
准备工作:安装并加载reshape2包
r
# 安装并加载reshape2包(包含dcast函数)
# install.packages("reshape2") # 如果未安装,取消注释运行
library(reshape2)
# 创建一个销售数据示例
sales <- data.frame(
product = c("A", "A", "B", "B", "C", "C", "A", "B", "C"),
region = c("North", "South", "North", "South", "North", "South", "East", "East", "East"),
quarter = c("Q1", "Q1", "Q1", "Q2", "Q2", "Q2", "Q3", "Q3", "Q3"),
amount = c(100, 150, 200, 120, 180, 130, 170, 210, 160)
)
print(sales)
1. dcast() 函数(从长格式转换为宽格式/数据透视表)
r
# dcast(data, formula, fun.aggregate, value.var)
# data: 要转换的数据框
# formula: 行变量 ~ 列变量
# fun.aggregate: 聚合函数(可选)
# value.var: 要填充到单元格的值列
# 基本数据透视:产品作为行,地区作为列,金额作为值
pivot1 <- dcast(sales, product ~ region, value.var = "amount")
print(pivot1)
# 输出:
# product East North South
# 1 A 170 100 150
# 2 B 210 200 120
# 3 C 160 180 130
# 如果有重复值,需要指定聚合函数
# 创建有重复数据的新示例
orders <- data.frame(
product = c("A", "A", "B", "A"),
city = c("BJ", "SH", "BJ", "BJ"),
sales = c(100, 200, 150, 50)
)
# 使用dcast时遇到重复组合会报错,需要用聚合函数
pivot_with_agg <- dcast(orders, product ~ city,
value.var = "sales",
fun.aggregate = sum) # 对重复值求和
print(pivot_with_agg)
# 输出:
# product BJ SH
# 1 A 150 200
# 2 B 150 NA
# 更复杂的透视表:行=产品,列=季度,值=金额和
pivot_complex <- dcast(sales, product ~ quarter,
value.var = "amount",
fun.aggregate = sum)
print(pivot_complex)
# 多变量作为行和列
pivot_multi <- dcast(sales, product + region ~ quarter,
value.var = "amount",
fun.aggregate = sum)
print(pivot_multi)
2. gather() 函数(来自tidyr包,宽格式转长格式)
r
# 安装并加载tidyr包
# install.packages("tidyr") # 如果未安装,取消注释运行
library(tidyr)
# 创建宽格式数据(类似透视后的结果)
wide_data <- data.frame(
product = c("A", "B", "C"),
Q1 = c(250, 200, 180),
Q2 = c(150, 120, 130),
Q3 = c(170, 210, 160)
)
print(wide_data)
# 输出:
# product Q1 Q2 Q3
# 1 A 250 150 170
# 2 B 200 120 210
# 3 C 180 130 160
# gather(data, key, value, ...)
# data: 要转换的数据框
# key: 新列名(存放原列名)
# value: 新列名(存放原值)
# ...: 要收集的列
# 将宽格式转换为长格式
long_data <- gather(wide_data,
key = "quarter", # 季度信息将存放在这一列
value = "amount", # 销售额将存放在这一列
Q1, Q2, Q3) # 指定要收集的列
print(long_data)
# 输出:
# product quarter amount
# 1 A Q1 250
# 2 B Q1 200
# 3 C Q1 180
# 4 A Q2 150
# 5 B Q2 120
# 6 C Q2 130
# 7 A Q3 170
# 8 B Q3 210
# 9 C Q3 160
# 使用负号排除不需要收集的列
long_data2 <- gather(wide_data,
key = "quarter",
value = "amount",
-product) # 除product外所有列都收集
print(long_data2) # 结果与上面相同
3. spread() 函数(长格式转宽格式,gather的逆操作)
r
# spread(data, key, value)
# data: 要转换的数据框
# key: 包含新列名的列
# value: 包含值的列
# 将上面转换的长格式数据恢复为宽格式
wide_recovered <- spread(long_data,
key = "quarter", # 用quarter列的值作为新列名
value = "amount") # 用amount列的值填充
print(wide_recovered)
# 输出应与原来的wide_data相同
# product Q1 Q2 Q3
# 1 A 250 150 170
# 2 B 200 120 210
# 3 C 180 130 160
# 复杂示例:处理需要聚合的情况
sales_long <- data.frame(
product = c("A", "A", "B", "B"),
quarter = c("Q1", "Q2", "Q1", "Q2"),
region = c("North", "South", "North", "South"),
amount = c(100, 150, 200, 120)
)
# spread在有重复组合时可能失败
# 先使用dcast或者先聚合再spread
library(dplyr)
sales_aggregated <- sales_long %>%
group_by(product, quarter) %>%
summarise(total_amount = sum(amount))
wide_sales <- spread(sales_aggregated,
key = "quarter",
value = "total_amount")
print(wide_sales)
# 输出:
# product Q1 Q2
# 1 A 100 150
# 2 B 200 120
四、综合案例:完整的数据分组统计与透视分析
r
# 加载必要的包
library(dplyr)
library(reshape2)
# 创建更完整的销售数据集
set.seed(123) # 设置随机种子,确保结果可重现
sales_data <- data.frame(
date = rep(c("2024-01", "2024-02", "2024-03"), each = 20),
product = sample(c("Laptop", "Phone", "Tablet"), 60, replace = TRUE),
region = sample(c("North", "South", "East", "West"), 60, replace = TRUE),
sales_amount = round(runif(60, 100, 1000), 0),
quantity = sample(1:20, 60, replace = TRUE)
)
head(sales_data)
# 1. 使用group_by和summarise进行分组统计
product_summary <- sales_data %>%
group_by(product) %>%
summarise(
total_sales = sum(sales_amount),
avg_sales = mean(sales_amount),
total_quantity = sum(quantity),
avg_quantity = mean(quantity),
transaction_count = n()
)
print("产品汇总统计:")
print(product_summary)
# 2. 多维度分组(产品 × 地区)
product_region_summary <- sales_data %>%
group_by(product, region) %>%
summarise(
total_revenue = sum(sales_amount),
avg_revenue = mean(sales_amount)
)
print("产品×地区销售统计:")
print(product_region_summary)
# 3. 使用aggregate进行分组统计
aggregate_result <- aggregate(sales_amount ~ product + region,
data = sales_data,
FUN = sum)
print("使用aggregate的产品×地区销售总额:")
print(aggregate_result)
# 4. 使用tapply进行分组统计
tapply_result <- tapply(sales_data$sales_amount,
list(sales_data$product, sales_data$region),
sum)
print("使用tapply的产品×地区销售矩阵:")
print(tapply_result)
# 5. 创建数据透视表
# 将产品作为行,月份作为列,销售总额作为值
sales_pivot <- dcast(sales_data, product ~ date,
value.var = "sales_amount",
fun.aggregate = sum)
print("产品销售月度透视表:")
print(sales_pivot)
# 6. 更复杂的透视:产品作为行,地区作为列,显示销售总额
region_pivot <- dcast(sales_data, product ~ region,
value.var = "sales_amount",
fun.aggregate = sum)
print("产品销售地区透视表:")
print(region_pivot)
# 7. 计算衍生指标(客单价)
product_metrics <- sales_data %>%
group_by(product) %>%
summarise(
total_revenue = sum(sales_amount),
total_units = sum(quantity),
avg_unit_price = total_revenue / total_units # 平均单价
)
print("产品指标分析:")
print(product_metrics)
五、要点回顾
r
# ==================== 要点回顾 ====================
# 1. 基础统计函数
# sum() - 求和
# mean() - 均值
# max() - 最大值
# min() - 最小值
# median()- 中位数
# var() - 方差
# sd() - 标准差
# quantile()- 分位数
# summary()- 综合统计
# 2. 分组统计家族
# tapply(值, 分组, 函数) - 按因子分组
# aggregate(公式, 数据, 函数) - 灵活的分组
# by(数据, 分组, 函数) - 对数据框分组
# split() + lapply() - 拆分后应用函数
# 3. apply家族
# apply(数组, 方向, 函数) - 矩阵/数据框
# lapply(列表, 函数) - 返回列表
# sapply(列表, 函数) - 简化结果
# 4. dplyr分组
# group_by() + summarise() - 最常用的分组汇总
# group_by() + mutate() - 添加分组统计列
# group_by() + filter() - 按组条件筛选
# 5. 数据重塑
# melt() - 宽转长(reshape2)
# dcast() - 长转宽/透视表(reshape2)
# gather() - 宽转长(tidyr)
# spread() - 长转宽(tidyr)
# 选择建议:
# - 简单分组统计用 tapply() 或 aggregate()
# - 复杂数据操作(多列、多函数)用 dplyr 的 group_by() + summarise()
# - 需要生成报表/透视表时用 dcast()
# - 数据清洗时用 gather()/spread() 调整数据结构
以上内容涵盖了R语言数据计算与分组统计的核心知识点,每个函数都配有详细的注释和实际案例,便于理解和应用。