数据可视化期末报告

Author

kaka

1 报告要求

  • 期末实验报告由5章节5个图形组成,每个章节需要作一个图形。

  • 每个章节选择作什么图自主选择,作图前补充完整图形标题名称,例如:图形1——多变量条形图。

  • 案例数据自主收集,不同章节可以公用一个数据集。但同学间不允许使用相同数据集。

  • 每个章节的数据集合需要通过datatable 函数展示,并简要解释数据来源和变量意义。

  • 每个输出图形后需要对图形作简要解读,最少需针对图形提出一个观点。

  • 渲染html文件保留代码展示,6月22日前将发布网址提交至共享文档“8、期末报告” 列中。

  • 评分标准:

    • 每章节图形各20分

    • 能有效输出图形和合理解释75%

    • 数据独特性强10%

    • 图形个性化强15%

2 类别数据可视化

2.1 案例数据解释与展示

course数据集包含课程信息,有课程ID、课程类目、课程总时长、课程章节数量、报名人数、完课率、课程发布平台数量、课程价格、课程评价、考试平均得分等属性,可用于方案决策、属性分析、聚类、预测等研究。
数据集属性说明如下:

  • Course_ID:课程ID

  • Category:课程类目(类别)

  • Duration (hours):课程总时长

  • Chapter_Number:课程章节数量

  • Enrolled_Students:报名人数(人数)

  • Completion_Rate (%):完课率

  • Platform_Number:课程发布平台数量

  • Price (¥):课程价格

  • Course_Evaluation:课程评价(5分制)

  • Examination_Average_Score:考试平均得分

#数据准备
data <- read.csv("F:/数据可视化/期末报告/courses.csv", stringsAsFactors = FALSE, fileEncoding = "UTF-8")
df<-data |> 
  select(Category,Enrolled_Students) |> 
  summarise(n=sum(Enrolled_Students),.by=Category) |> 
  rename(类别=Category,人数=n ) |> 
  arrange(desc(人数)) |> 
  mutate(累积百分比 = cumsum(人数*100/sum(人数)), #计算累积百分比
         累积百分比 = round(累积百分比,1),        #保留一位小数 
         类别 = fct_inorder(类别)         #按字符出现顺序定义因子水平
         )

datatable(df,rownames = FALSE)

2.2 图形1——帕累托图

  • 按学生人数排序的课程类别柱状图

  • 红色累积百分比曲线

  • 双Y轴显示绝对人数和相对百分比

  • 自动适应的颜色和标签

# 创建帕累托图
pareto <- ggplot(df, aes(x = 类别)) +
  # 柱状图(人数)
  geom_col(aes(y = 人数, fill = 类别), 
           width = 0.7, alpha = 0.8) +
  # 折线图(累积百分比)
  geom_line(aes(y = 累积百分比 * max(人数)/100, group = 1), 
            color = "red", linewidth = 1) +
  # 点图(累积百分比)
  geom_point(aes(y = 累积百分比 * max(人数)/100), 
             color = "red", size = 3) +
  # 添加累积百分比标签
  geom_text(aes(y = 累积百分比 * max(人数)/100, 
                label = paste0(累积百分比, "%")),
            vjust = -1, color = "red", size = 3.5) +
  # 添加人数标签
  geom_text(aes(y = 人数, label = 人数),
            vjust = -0.5, size = 3) +
  # 双Y轴设置
  scale_y_continuous(
    name = "学生人数",
    sec.axis = sec_axis(~ ./(max(df$人数)/100), 
                        name = "累积百分比(%)")
  ) +
  # 颜色和主题设置
  scale_fill_brewer(palette = "Set3") +
  labs(title = "课程类别学生人数帕累托图",
       x = "课程类别") +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
    legend.position = "none",
    panel.grid.major = element_line(color = "gray90"),
    panel.grid.minor = element_blank()
  )

# 显示图形
pareto

2.3 心得体会:

  1. 数据准备

    需要先对数据进行排序,按学生人数降序排列

    计算累积百分比是创建帕累托图的关键步骤

  2. 双Y轴处理

    通过scale_y_continuous()sec_axis()实现了主次双Y轴,这是帕累托图的核心

    且使用twinx()创建第二个Y轴用于百分比

    心得:理解这种转换关系是创建双轴图表的关键,需要确保两个轴的数值范围匹配

  3. 图层叠加的艺术

    scale_fill_brewer(palette = "Set3")提供了专业的配色方案

    代码通过叠加多个几何对象(geom_col, geom_line, geom_point)构建完整图表

    每个几何对象都有明确的用途:柱状图展示原始数据,折线和点图展示累积百分比

  4. 格式化挑战

    科学计数法转换需要特别处理

    通过vjust参数微调标签位置避免重叠

  5. 可读性优化

    使用geom_text添加了两类标签:人数值和百分比值

    旋转x轴标签避免重叠

    控制标注密度,避免图表过于拥挤

2.4 图表特点分析:

  1. 图表类型:这是一个帕累托图(Pareto Chart),用于显示不同课程类别的学生人数分布情况,并展示累积百分比。

  2. 数据特点

    显示了多个课程类别的学生人数,最高约375,326人,最低约75人

    包含累积百分比线,最高达到81.2%

    各柱形高度差异显著,表明学生人数在不同课程类别间分布不均

3 数据分布可视化

3.1 案例数据解释与展示

  • online_courses数据集是941门在线课程的信息,信息内容含有课程ID、名称、类别、持续时间、注册、完成率、上线平台、价格和评价排名等属性。它提供了4个平台和各种课程类别的数据,可用于分析在线学习趋势、比较平台、可视化报告和构建预测模型。

    数据内容说明:
    Course_ID:课程ID
    Course_Name:课程名称
    Category:课程类目
    Duration (hours):课程持续时长
    Enrolled_Students:报名学生人数
    Completion_Rate (%):完课率
    Platform:课程上线平台
    Price ($):课程价格
    Rank:课程排名

data <- read.csv("F:/数据可视化/期末报告/online_courses.csv", stringsAsFactors = FALSE, fileEncoding = "UTF-8")
datatable(data)
data$Enrolled_Students <- as.numeric(as.character(data$Enrolled_Students))

3.2 图形2——单变量直方图(Enrolled_Students:报名学生人数)

# 加载必要的包
library(ggplot2)
library(e1071)   # 用于计算偏度和峰度
library(scales)  # 用于格式化坐标轴

# 自定义主题
mytheme <- theme_bw() +
  theme(
    plot.title = element_text(size = 16, hjust = 0.5),
    axis.title = element_text(size = 14),
    axis.text = element_text(size = 12),
    legend.position = "top",
    legend.title = element_blank(),
    panel.grid.major = element_line(color = "grey80", linetype = "dashed"),
    panel.grid.minor = element_blank()
  )

# 计算统计量
mean_val <- mean(data$Enrolled_Students, na.rm = TRUE)
median_val <- median(data$Enrolled_Students, na.rm = TRUE)
skewness_val <- skewness(data$Enrolled_Students, na.rm = TRUE)
kurtosis_val <- kurtosis(data$Enrolled_Students, na.rm = TRUE)

# 创建直方图
ggplot(data, aes(x = Enrolled_Students)) +
  geom_histogram(aes(y = ..density..), 
                 bins = 30, 
                 fill = "steelblue", 
                 color = "white", 
                 alpha = 0.7) +
  geom_density(color = "red", size = 1) +  # 核密度曲线
  geom_rug(sides = "b", color = "darkgreen", alpha = 0.5) +  # 地毯图
  geom_vline(xintercept = mean_val, 
             color = "blue", 
             linetype = "dashed", 
             size = 1) +  # 均值参考线
  geom_point(aes(x = median_val, y = 0), 
             color = "purple", 
             size = 3) +  # 中位数参考点
  annotate("text", 
           x = median_val, 
           y = 0.0001, 
           label = paste("Median:", round(median_val, 1)), 
           color = "purple", 
           vjust = -1) +  # 中位数注释
  annotate("text", 
           x = Inf, y = Inf, 
           label = paste("偏度Skewness:", round(skewness_val, 2)), 
           hjust = 1.1, vjust = 2, 
           color = "black") +  # 偏度注释
  annotate("text", 
           x = Inf, y = Inf, 
           label = paste("峰度Kurtosis:", round(kurtosis_val, 2)), 
           hjust = 1.1, vjust = 4, 
           color = "black") +  # 峰度注释
  scale_x_continuous(labels = comma) +  # 格式化x轴标签
  labs(title = "报名学生人数分布直方图",
       x = "报名学生人数",
       y = "学生人数分布密度") +
  mytheme

3.3 图形解读

该直方图展示了学生注册人数的分布情况,从图形可以得出以下关键信息:

  • 数据呈现近似正态分布,注册人数主要集中在3,000-4,000区间,峰值密度约6e-04;

  • 偏度系数0.16显示分布略微右偏,峰度系数2.46表明数据分布比正态分布更平缓,尾部较薄。学生人数集中在中间范围,极端值(极高或极低注册人数的课程)较少。

  • 值和中位数(3354)位置接近,约50%的课程注册人数≤3354人,另一半≥3354人,进一步验证了分布的对称性;

  • 最高密度出现在 3,000–4,000人 区间(参考x轴标注),说明大多数课程的注册人数在此范围内。

  • 地毯图显示在2000-5000区间有少量极端值,但整体数据集中;

  • 科学计数法的y轴标签和千位分隔符的x轴标签使大数字阅读更清晰。

3.4 代码心得体会

根据ggplot2代码通过多层叠加实现了专业统计可视化:

  • 密度直方图geom_histogram(aes(y=..density..))将频数转换为密度,使不同样本量的数据可比

  • 核密度曲线geom_density()完美叠加在直方图上,直观展示数据分布的平滑形态

  • 地毯图geom_rug()在坐标轴边缘显示原始数据点,有效补充分布细节

  • 统计量标注:通过annotate()添加的偏度(0.16)和峰度(2.46)数值,快速判断分布形态

  • 参考线/点geom_vline()geom_point()标记的均值和中位数(3354),直观显示数据集中趋势

  • 自动计算e1071包的skewness()kurtosis()函数简化了统计量计算过程

4 变量关系可视化

4.1 案例数据解释与展示

data <- read.csv("F:/数据可视化/期末报告/online_courses.csv", stringsAsFactors = FALSE, fileEncoding = "UTF-8")
datatable(data)

4.2 图形3——在线课程持续时间与完成率关系散点图

# 数据预处理
# 将Duration (hours)转换为数值型
data$Duration..hours. <- as.numeric(data$Duration..hours.)

# 将Completion_Rate转换为数值型(处理百分号)
data$Completion_Rate <- as.numeric(gsub("%", "", data$Completion_Rate))

# 检查转换结果
str(data)
'data.frame':   941 obs. of  10 variables:
 $ Course_ID          : int  520 503 751 72 800 544 586 347 162 602 ...
 $ Course_Name        : chr  "Course_520" "Course_503" "Course_751" "Course_72" ...
 $ Category           : chr  "Business" "Business" "Data Science" "Data Science" ...
 $ Duration..hours.   : num  40 40 40 40 40 40 40 40 40 40 ...
 $ Enrolled_Students  : int  4113 2541 3220 4176 4563 2769 3381 3535 3685 2284 ...
 $ Completion_Rate....: num  84.4 73.4 77.7 88.3 92.3 ...
 $ Platform           : chr  "LinkedIn Learning" "LinkedIn Learning" "Udemy" "Coursera" ...
 $ Price....          : num  74.7 97.2 67.5 88.9 72.9 ...
 $ Rank               : num  4.91 4.2 4.36 4.66 4.85 ...
 $ Completion_Rate    : num  84.4 73.4 77.7 88.3 92.3 ...
summary(data[c("Duration..hours.", "Completion_Rate")])
 Duration..hours. Completion_Rate
 Min.   : 40.00   Min.   :70.01  
 1st Qu.: 62.00   1st Qu.:77.88  
 Median : 77.00   Median :83.79  
 Mean   : 74.36   Mean   :84.19  
 3rd Qu.: 89.00   3rd Qu.:89.66  
 Max.   :100.00   Max.   :99.99  
# 3. 绘制散点图
scatter_plot <- ggplot(data, aes(x = Duration..hours., y = Completion_Rate)) +
  geom_point(color = "#3498db", size = 3, alpha = 0.7) +  # 使用蓝色点
  geom_smooth(method = "lm", se = FALSE, color = "#e74c3c") +  # 添加趋势线
  labs(title = "在线课程持续时间与完成率关系",
       subtitle = "数据来源:online_courses.csv",
       x = "课程持续时间 (小时)",
       y = "课程完成率 (%)",
       caption = "注:完成率已转换为百分比数值") +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
    plot.subtitle = element_text(hjust = 0.5, color = "gray50"),
    axis.title = element_text(size = 12),
    panel.grid.major = element_line(color = "gray90"),
    panel.grid.minor = element_blank()
  )

# 显示散点图
print(scatter_plot)

4.3 图表含义

  • 该散点图展示了在线课程持续时间(小时)课程完成率(%)之间的关系,旨在分析课程时长是否影响学习者的完成率

  • X轴:课程持续时间(小时),数值型变量

  • Y轴:课程完成率(%),数值型变量(已去除百分号转换)

  • 蓝色点:每个点代表一门课程,横纵坐标分别对应其持续时间和完成率

  • 红色趋势线:采用线性回归(method = "lm")拟合数据,反映两变量的整体相关性

4.4 心得体会:

4.4.0.1 1、数据特点

  • 变量转换

    Duration (hours)as.numeric(确保数值计算正确);Completion_Rate → 去除百分号后转换为数值(如”85%” → 85

  • 数据检查

    str(data) 验证变量类型转换是否成功;summary() 查看两变量的分布(最小值、最大值、中位数等)

  • 点的分布

    若点呈右上趋势(趋势线斜率为正),说明课程时间越长,完成率可能越高(学习者更愿意完成长期课程)。

    若点呈右下趋势(斜率为负),则短期课程的完成率更高(学习者可能因时间投入少更易坚持)。

    若点无明显趋势(趋势线接近水平),则两者无显著关联。

  • 异常值

    偏离趋势线的点(如某门课程时间短但完成率极低)可能需进一步分析原因(如课程难度、内容质量)。

5 样本相似性可视化

5.1 案例数据解释与展示

data <- read.csv("F:/数据可视化/期末报告/online_courses.csv", stringsAsFactors = FALSE, fileEncoding = "UTF-8")
datatable(data)

5.2 图形4——不同平台在线课程指标对比(雷达图)

# 加载必要的库
library(ggiraphExtra)
library(ggplot2)
library(dplyr)
library(tidyr)

# 读取数据
data <- read.csv("online_courses.csv")

# 选择需要分析的数值型变量(排除非数值型变量和ID类变量)
numeric_vars <- data %>% 
  select(Duration..hours., Enrolled_Students, Completion_Rate...., Price...., Rank) %>% 
  names()

# 按Platform分组计算均值
radar_data <- data %>%
  group_by(Platform) %>%
  summarise(across(all_of(numeric_vars), mean, na.rm = TRUE))  # 修正括号

# 绘制雷达图
ggRadar(
  data = radar_data,
  aes(group = Platform),
  interactive = FALSE,  # 设置为TRUE可生成交互式图形
  rescale = TRUE,       # 将各变量缩放到相同范围
  legend.position = "right",
  size = 1,
  alpha = 0.3
) +
  labs(title = "不同平台在线课程指标对比(雷达图)",
       caption = "数据来源:online_courses.csv") +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    legend.text = element_text(size = 8)  # 修正为英文括号
  )

5.3 图形解析:

5.3.1 1. 学生报名情况(Enrolled_Students)

  • Coursera:注册人数表现突出,可能是由于平台知名度高、课程种类丰富

  • Udemy:注册人数次之,反映其大众化定价策略和广泛课程覆盖的优势

  • LinkedIn Learning:注册人数中等,与其职业导向的垂直用户群体特征相符

  • edX:注册人数相对较低,可能因其更专注高等教育和认证课程

报名趋势:Coursera > Udemy > LinkedIn Learning > edX

5.3.2 2. 课程完成率(Completion_Rate)

  • LinkedIn Learning:完成率最高,可能与职场用户的学习目的性强有关

  • Coursera:完成率次之,得益于其结构化课程设计和证书激励

  • edX:完成率中等,部分用户可能只旁听不追求完课

  • Udemy:完成率最低,或因用户多为碎片化学习,缺乏强制进度

完成率趋势:LinkedIn Learning > Coursera > edX > Udemy

5.4 心得体会:

  1. 数据可视化是数据分析的利器
  • 雷达图能直观展示多维度的平台对比,一眼就能看出Coursera在注册人数上的绝对优势和LinkedIn Learning在完成率上的突出表现

  • 通过图形化呈现,复杂的多维数据比较变得简单易懂,这是纯数字表格无法实现的

  1. 数据清洗和预处理至关重要
  • 原始数据中的变量名包含特殊符号(如..),需要规范处理

  • 对缺失值(na.rm=TRUE)的处理保证了分析的准确性

  • 分组计算均值前确认数据类型是数值型,避免了分析错误

  1. 选择合适的图表类型很关键
  • 雷达图特别适合比较3个以上平台在5-6个维度的表现

  • 通过rescale=TRUE参数自动标准化不同量纲的指标,使比较更合理

  • 交互式选项(interactive)为后续深度探索提供了可能

6 时间序列可视化

6.1 案例数据解释与展示

data <- read.csv("F:/数据可视化/期末报告/shanghai_index_2024.csv", stringsAsFactors = FALSE, fileEncoding = "UTF-8")
datatable(data)

6.2 图形5——上海指数价格走势(按成交额区间分面图)

library(ggplot2)
library(dplyr)
library(scales)

data <- read.csv("shanghai_index_2024.csv") %>%
  mutate(
    日期 = as.Date(日期),
    成交额区间 = cut(
      成交额,
      breaks = quantile(成交额, probs = seq(0, 1, 0.25), na.rm = TRUE),
      labels = c("低", "中低", "中高", "高"),
      include.lowest = TRUE
    )
  )

ggplot(data, aes(x = 日期)) +
  geom_area(aes(y = 收盘, fill = "收盘价"), alpha = 0.6) +
  geom_area(aes(y = 开盘, fill = "开盘价"), alpha = 0.6) +
  geom_area(aes(y = 最高, fill = "最高价"), alpha = 0.4) +
  geom_area(aes(y = 最低, fill = "最低价"), alpha = 0.4) +
  facet_wrap(
    ~成交额区间, 
    ncol = 2, 
    labeller = labeller(成交额区间 = function(x) paste("成交额:", x))
  ) +
  scale_fill_manual(
    values = c("开盘价" = "#4DAF4A", "收盘价" = "#377EB8", "最高价" = "#E41A1C", "最低价" = "#984EA3"),
    name = "价格类型"
  ) +
  scale_y_continuous(labels = comma) +
  labs(title = "上海指数价格走势(按成交额区间分面图)", x = "日期", y = "价格") +
  theme_minimal() +
  theme(
    legend.position = "bottom",
    plot.title = element_text(hjust = 0.5, face = "bold"),
    axis.text.x = element_text(angle = 45, hjust = 1, size = 8),
    strip.text = element_text(face = "bold")  # 分面标题加粗
  )

6.3 图片解读:

  1. 分面布局

    成交额区间 分面显示(低、中低、中高、高),共4个子图。

    每个子图显示 开盘价、收盘价、最高价、最低价 的叠加面积图。

  2. Y轴(价格)

    价格范围在 0-3,000 之间。

    使用了 scales::comma 格式化数字(如 3,000)。

  3. X轴(日期)

    横轴显示 2024年1月 至 2025年12月 的日期。

    标签可能存在重叠(如“1月 2024”重复出现),需优化。

6.4 心得体会:

6.4.1 1. 数据预处理:稳健性优先

  • 关键点

    列名检查:确保CSV列名与代码中的变量名完全一致(如成交额 vs 成交额,避免中英文混用)。

    日期格式化:用 as.Date() 统一日期格式,避免后续绘图时X轴解析错误。

    分组逻辑:使用 cut() + quantile() 分组时,务必加 na.rm = TRUE 处理缺失值。

6.4.2 2. 可视化设计:图层叠加与分面技巧

  • 关键点

    面积图叠加:通过 geom_area()alpha 参数控制透明度,避免完全遮挡。

    分面优化facet_wrap()scales = "free_y" 允许Y轴自适应,避免比例扭曲。

    颜色映射:将颜色映射到分类变量(如fill = "开盘价"),而非硬编码。