第四章 数据分布可视化

Author

221527138李旺仔

1 解释原始数据

  • faithful是R语言中自带的一个经典数据集,它记录了美国黄石国家公园老忠实间歇泉(Old Faithful geyser)的喷发数据。这个数据集经常被用于统计教学和数据分析示例。

  • faithful数据集包含两个变量,共有272个观测值。

    data = faithful
    datatable(data,rownames = FALSE)
  • eruptions: 喷发持续时间,连续数值变量,以分钟为单位,范围:1.6分钟到5.1分钟。

  • waiting: 两次喷发之间的等待时间,连续数值变量,以分钟为单位,范围:43分钟到96分钟。

2 单变量直方图

2.1 绘图要求

  • 利用geom_histogram(aes(y=..density..))绘制eruptions的直方图,使用预设主题:mytheme;

  • 利用geom_rug()为直方图添加地毯图;

  • 利用geom_density()为直方图添加核密度曲线;

  • 利用annotate()在直方图标注峰度和偏度信息;

  • 利用geom_vline() 为直方图添加一条垂直的均值参考线;

  • 利用geom_point()在横轴上添加一个中位数参考点,并在点上方添加文字注释

2.2 作图代码

library(e1071)

df<-data
ggplot(data=df,aes(x=eruptions))+mytheme+    # 绘制直方图
  geom_histogram(aes(y=..density..),fill="lightgreen",color="gray50")+
  geom_rug(size=0.2,color="blue3")+  # 添加地毯图,须线的宽度为0.2
  geom_density(color="blue2",size=0.7)+ # 添加核密度曲线
  annotate("text",x=2.5,y=0.7,label=paste0("偏度系数 =",round(skewness(df$eruptions),3)),size=3)+  # 添加注释文本
    annotate("text",x=2.5,y=0.5,label="峰度系数 =",size=3)+  # 添加注释文本
  annotate("text",x=3,y=0.5,label=round(kurtosis(df$eruptions),3),size=3)+  # 添加峰度系数
  geom_vline(xintercept=mean(df$eruptions),linetype="twodash",size=0.6,color="red") +        # 添加均值垂线,并设置线形、线宽和颜色
  annotate("text", x=3.8, y=0.7, label=paste0("均值 = ", round(mean(df$eruptions), 3)), size=3)+
  geom_point(x=median(df$eruptions),y=0,shape=21,size=4,fill="yellow")+ # 添加中位数点
annotate("text",x=median(df$eruptions),y=0.05,label="中位数",size=3,color="red3") # 添加注释文本

2.3 图形观察和代码编写的心得体会

  • 复制原本代码,修改变量名,观察图例位置最后完成修改。qmd文件可以一边改一边看,可以提高效率。看不懂的地方可以问ai解答。

3 叠加直方图和镜像直方图

3.1 绘图要求

  • 绘制eruptionswaiting两个变量的叠加直方图和镜像直方图,使用预设主题:mytheme。

  • 将数据转化为长型数据再作叠加直方图,利用scale_fill_brewer()将叠加直方图配色方案改为set3

  • 镜像直方图中eruptions在正方向,waiting在负方向,直方数bins=30,并添加文字标签作标签。

  • 两种图都需要针对原始数据作图和标准标准化数据作图,可以使用scale()函数对变量标准化,分类标准化可以使用plyr::ddply()函数。

3.2 叠加直方图代码

df <- data |>  
  gather(eruptions,waiting,key=指标,value=指标值) %>%  # 融合数据
  ddply("指标",transform,标准化值=scale(指标值)) # 计算标准化值并返回数据框

DT::datatable(df,rownames = FALSE)
# 图(a)叠加直方图
p1<-ggplot(df)+aes(x=指标值,y=..density..,fill=指标)+
  geom_histogram(position="identity",color="gray60",alpha=0.5)+
  theme(legend.position=c(0.8,0.8),# 设置图例位置
       legend.background=element_rect(fill="grey90",color="grey"))+  
  scale_fill_brewer(palette = "Set3") +  # 使用 Set3 配色
                                                # 设置图例背景色和边框颜色
  ggtitle("(a) AQI和PM2.5的叠加直方图")

p2<-ggplot(df)+aes(x=标准化值,y=..density..,fill=指标)+
      scale_fill_brewer(palette = "Set3") +  # 使用 Set3 配色
  geom_histogram(position="identity",color="gray60",alpha=0.5)+
  theme(legend.position=c(1,0.8),# 设置图例位置
       legend.background=element_rect(fill="grey90",color="grey"))

gridExtra::grid.arrange(p1,p2,ncol=2)        # 组合图形

3.3 镜像直方图代码

data <- data %>% 
  mutate(
    std.eruptions=scale(eruptions),
    std.waiting=scale(waiting)
    )
# 图(b)镜像直方图
p1<-ggplot(data)+aes(x=x)+
   geom_histogram(aes(x=eruptions,y=..density..),color="grey50",fill="red",alpha=0.3)+ # 绘制eruptions的直方图(上图)
   geom_label(aes(x=20,y=0.1),label="eruptions",color="red")+  # 添加标签
   geom_histogram(aes(x=waiting,y=-..density..),color="grey50",fill="blue",alpha=0.3)+ # 绘制waiting的直方图(下图)
   geom_label(aes(x=80,y=-0.1),label="waiting",color="blue")+  # 添加标签
   xlab("指标值")+ggtitle("(b) eruptions和 waiting的镜像直方图")


# 图(b)镜像直方图
p2<-ggplot(data)+aes(x=x)+
   geom_histogram(aes(x=std.eruptions,y=..density..),color="grey50",fill="red",alpha=0.3)+ # 绘制eruptions的直方图(上图)
   geom_label(aes(x=0.010,y=0.1),label="eruptions",color="red")+  # 添加标签
   geom_histogram(aes(x=std.waiting,y=-..density..),color="grey50",fill="blue",alpha=0.3)+ # 绘制waiting的直方图(下图)
   geom_label(aes(x=0.10,y=-0.1),label="waiting",color="blue")+  # 添加标签
   xlab("指标值")+ggtitle("(b) eruptions和 waiting的镜像直方图")
gridExtra::grid.arrange(p1,p2,ncol=2)        # 组合图形

3.4 图形观察和代码编写的心得体会

  • 镜像直方图清晰对比eruptions和waiting的分布。左图未标准化,eruptions(0-5)范围窄,waiting(40-100)范围广,分布差异大。右图标准化后,std.eruptions和std.waiting范围一致(-2到2),均呈双峰分布,方便比较形状和对称性。

  • ggplot2绘制镜像直方图,y=..density..和y=-..density..实现上下对称,alpha=0.3增强透明度,标签用geom_label标注清晰。grid.arrange组合图形,布局直观,便于对比标准化前后的分布差异。

4 核密度图

4.1 绘图要求

  • 绘制eruptions和 waiting两个变量的分组核密度图、分面核密度图和镜像核密度图。

  • 分组核密度图,采用geom_density(position="identity")

  • 分面核密度图,采用geom_density()+facet_wrap(~xx,scale="free")

  • 镜像核密度图中eruptions在正方向,waiting在负方向,直方数bins=30,并添加文字标签作标签。

  • 分组核密度图和镜像核密度图需要针对原始数据作图和标准标准化数据作图。

4.2 分组核密度图

df <- data |>  
  gather(eruptions,waiting,key=指标,value=指标值) %>%  # 融合数据
  ddply("指标",transform,标准化值=scale(指标值)) # 计算标准化值并返回数据框

DT::datatable(df,rownames = FALSE)
# 图(a)叠加直方图
p1<-ggplot(df)+aes(x=指标值,y=..density..,fill=指标)+
  geom_density(position="identity",color="gray60",alpha=0.5)+
  theme(legend.position=c(0.8,0.8),# 设置图例位置
       legend.background=element_rect(fill="grey90",color="grey"))+  
  scale_fill_brewer(palette = "Set3") +  # 使用 Set3 配色
                                                # 设置图例背景色和边框颜色
  ggtitle("(a) eruptions和 waiting的核密度图")

p2<-ggplot(df)+aes(x=标准化值,y=..density..,fill=指标)+
      scale_fill_brewer(palette = "Set3") +  # 使用 Set3 配色
  geom_density(position="identity",color="gray60",alpha=0.5)+
  theme(legend.position=c(1,0.8),# 设置图例位置
       legend.background=element_rect(fill="grey90",color="grey"))

gridExtra::grid.arrange(p1,p2,ncol=2)        # 组合图形

4.3 分面核密度图

ggplot(df)+aes(x=指标值,y=..density..,fill=指标)+
  geom_density()+facet_wrap(~指标,scale="free")+
  geom_density(position="identity",color="gray60",alpha=0.5)+
  theme(legend.position=c(0.5,1),# 设置图例位置
       legend.background=element_rect(fill="grey90",color="grey"))+  
  guides(fill="none")+
  scale_fill_brewer(palette = "Set3")   # 使用 Set3 配色

                                               #设置图例背景色和边框颜色

4.4 镜像核密度图

data <- data %>% 
  mutate(
    std.eruptions=scale(eruptions),
    std.waiting=scale(waiting)
    )
# 图(b)镜像直方图
p1<-ggplot(data)+aes(x=x)+
   geom_density(aes(x=eruptions,y=..density..),color="grey50",fill="red",alpha=0.3)+ # 绘制eruptions的直方图(上图)
   geom_label(aes(x=20,y=0.1),label="eruptions",color="red")+  # 添加标签
   geom_density(aes(x=waiting,y=-..density..),color="grey50",fill="blue",alpha=0.3)+ # 绘制waiting的直方图(下图)
   geom_label(aes(x=80,y=-0.1),label="waiting",color="blue")+  # 添加标签
   xlab("指标值")+ggtitle("(b) eruptions和 waiting的镜像核密度图")


# 图(b)镜像直方图
p2<-ggplot(data)+aes(x=x)+
   geom_density(aes(x=std.eruptions,y=..density..),color="grey50",fill="red",alpha=0.3)+ # 绘制eruptions的直方图(上图)
   geom_label(aes(x=0.010,y=0.1),label="eruptions",color="red")+  # 添加标签
   geom_density(aes(x=std.waiting,y=-..density..),color="grey50",fill="blue",alpha=0.3)+ # 绘制waiting的直方图(下图)
   geom_label(aes(x=0.10,y=-0.1),label="waiting",color="blue")+  # 添加标签
   xlab("指标值")+ggtitle("(b) eruptions和 waiting的镜像核密度图")
gridExtra::grid.arrange(p1,p2,ncol=2)        # 组合图形

4.5 图形观察和代码编写的心得体会

  • 镜像图突出两变量差异,分面图适合多变量独立分析,分组图适合少变量直接对比。ggplot2的灵活性让我能通过调整参数(如alpha、color)优化视觉效果,未来我会更注重图形可读性和代码简洁性。

5 箱线图和小提琴图

5.1 绘图要求

  • 根据实际数据和标准化后的数据绘制eruptionswaiting两个变量的箱线图geom_boxplot和小提琴图geom_violin

  • 采用stat_summary(fun="mean",geom="point")在箱线图和均值图中要添加均值点。

  • 小提琴图中要加入点图和箱线图

  • 采用调色板前两种颜色,brewer.pal(6,"Set2")[1:2] ,作为箱体填充颜色。

"#66C2A5" "#FC8D62" "#8DA0CB" "#E78AC3" "#A6D854" "#FFD92F"

5.2 箱线图代码

# 数据标准化
data <- data %>% 
  mutate(
    std.eruptions = scale(eruptions),
    std.waiting = scale(waiting)
  )

# 准备数据:将实际数据和标准化数据转换为长格式以便绘图
data_long <- data %>%
  tidyr::pivot_longer(cols = c(eruptions, waiting), names_to = "variable", values_to = "value")
data_std_long <- data %>%
  tidyr::pivot_longer(cols = c(std.eruptions, std.waiting), names_to = "variable", values_to = "value")

# 箱线图(实际数据)
p_box1 <- ggplot(data_long, aes(x = variable, y = value, fill = variable)) +
  geom_boxplot(alpha = 0.7) +
  stat_summary(fun = "mean", geom = "point", shape = 23, size = 3, fill = "black") +
  scale_fill_manual(values = brewer.pal(6, "Set2")[1:2]) +
  xlab("变量") + ylab("值") +
  ggtitle("(a) 实际数据的箱线图") +
  theme(legend.position = c(0.4, 0.8), # 图例放在
        legend.background = element_rect(fill = "transparent")) # 图例背景透明

# 箱线图(标准化数据)
p_box2 <- ggplot(data_std_long, aes(x = variable, y = value, fill = variable)) +
  geom_boxplot(alpha = 0.7) +
  stat_summary(fun = "mean", geom = "point", shape = 23, size = 3, fill = "black") +
  scale_fill_manual(values = brewer.pal(6, "Set2")[1:2]) +
  xlab("变量") + ylab("值") +
  ggtitle("(b) 标准化数据的箱线图") +
  theme(legend.position = c(0.9, 0.9),
        legend.background = element_rect(fill = "transparent"))

# 组合图形
gridExtra::grid.arrange(p_box1, p_box2,  ncol =2 )

5.3 小提琴图代码

  • 通过d3r::d3_nest将数据框转化为层次数据“d3.js”作为绘图输入
# 小提琴图(实际数据)
p_violin1 <- ggplot(data_long, aes(x = variable, y = value, fill = variable)) +
  geom_violin(alpha = 0.7) +
  geom_boxplot(width = 0.2, fill = "white", alpha = 0.5) +
  geom_point(aes(color = variable), position = position_jitter(width = 0.1), size = 1, alpha = 0.5) +
  stat_summary(fun = "mean", geom = "point", shape = 23, size = 3, fill = "black") +
  scale_fill_manual(values = brewer.pal(6, "Set2")[1:2]) +
  scale_color_manual(values = brewer.pal(6, "Set2")[1:2]) +
  xlab("变量") + ylab("值") +
  ggtitle("(c) 实际数据的小提琴图") +
  theme(legend.position = "none") # 删除图例

# 小提琴图(标准化数据)
p_violin2 <- ggplot(data_std_long, aes(x = variable, y = value, fill = variable)) +
  geom_violin(alpha = 0.7) +
  geom_boxplot(width = 0.2, fill = "white", alpha = 0.5) +
  geom_point(aes(color = variable), position = position_jitter(width = 0.1), size = 1, alpha = 0.5) +
  stat_summary(fun = "mean", geom = "point", shape = 23, size = 3, fill = "black") +
  scale_fill_manual(values = brewer.pal(6, "Set2")[1:2]) +
  scale_color_manual(values = brewer.pal(6, "Set2")[1:2]) +
  xlab("变量") + ylab("值") +
  ggtitle("(d) 标准化数据的小提琴图") +
  theme(legend.position = "none") # 删除图例
gridExtra::grid.arrange(p_violin1, p_violin2,  ncol =2 )

5.4 图形观察和代码编写的心得体会

  • 图形观察:箱线图清晰展示中位数、四分位距和离群点,小提琴图结合点图和箱线图更全面地反映分布形状和数据点分布。标准化后数据范围一致,便于比较。
  • 代码编写:ggplot2的图层叠加(如小提琴图内嵌箱线图和点图)功能强大,stat_summary添加均值点简洁高效。brewer.pal配色美观,grid.arrange布局灵活,适合多图对比展示。

6 威尔金森点图、蜂群图和云雨图

6.1 绘图要求

  • 绘制eruptionswaiting 两个变量的威尔金森点图、蜂群图和云雨图。

  • 三种图形均采用标准化数据作图

  • 威尔金森点图采用geom_dotplot(binaxis="y",bins=30,dotsize = 0.3) ,要求作出居中堆叠和向上堆叠两种情况的图。

  • 蜂群图采用geom_beeswarm(cex=0.8,shape=21,size=0.8),要求作出不带箱线图和带有箱线图两种情况的图。

  • 云雨图采用geom_violindot(dots_size=0.7,binwidth=0.07) ,要求作出横向和纵向图两种情况的图。

6.2 威尔金森点图代码

分别作矩形热图和极坐标热图

# 标准化数据
df <- faithful |> 
  mutate(eruptions = scale(eruptions)[,1],
         waiting = scale(waiting)[,1]) |> 
  pivot_longer(cols = everything(), names_to = "变量", values_to = "值")
# 居中堆叠
p1 <- ggplot(df, aes(x=变量, y=值)) +
  geom_dotplot(binaxis="y", stackdir="center", bins=30, dotsize=0.3, fill="black") +
  theme_bw() +
  ggtitle("(a) 威尔金森点图 - 居中堆叠")

# 向上堆叠
p2 <- ggplot(df, aes(x=变量, y=值)) +
  geom_dotplot(binaxis="y", stackdir="up", bins=30, dotsize=0.3, fill="black") +
  theme_bw() +
  ggtitle("(b) 威尔金森点图 - 向上堆叠")

gridExtra::grid.arrange(p1, p2,  ncol =2 )

6.3 蜂群图代码

mytheme<-theme_bw()+theme(legend.position="none")
mytheme <- theme_bw() +
  theme(legend.position = "none",
        plot.title = element_text(size = 14, hjust = 0.5))

# 仅蜂群图
p1 <- ggplot(df, aes(x = 变量, y = 值, color = 变量)) +
  geom_beeswarm(cex = 0.8, shape = 21, size = 0.8) +
  mytheme +
  ggtitle("(c) 蜂群图")

# 箱线图 + 蜂群图
p2 <- ggplot(df, aes(x = 变量, y = 值, color = 变量)) +
  geom_boxplot(size = 0.5, outlier.size = 0.8) +
  geom_beeswarm(shape = 21, cex = 0.8, size = 0.8) +
  mytheme +
  ggtitle("(d) 箱线图 + 蜂群图")

# 并排展示两个图
gridExtra::grid.arrange(p1, p2, ncol = 2)

6.4 云雨图代码

# 加载必要库
library(ggplot2)
library(ggdist)       # 提供 geom_violindot()
library(see)          # 提供 theme_modern()
library(dplyr)
library(tidyr)
library(gridExtra)

# 加载数据
data(faithful)

# 标准化数据并转成长格式
df1 <- faithful |>
  mutate(eruptions = scale(eruptions)[,1],
         waiting = scale(waiting)[,1]) |>
  pivot_longer(cols = everything(), names_to = "指标", values_to = "指标值")

# 自定义主题
mytheme <- theme_modern() +
  theme(legend.position = "none",
        plot.title = element_text(size = 14, hjust = 0.5))

# 图 (a):垂直排列云雨图
p1 <- ggplot(df1, aes(x = 指标, y = 指标值, fill = 指标)) +
  geom_violindot(dots_size = 0.7, binwidth = 0.07) +  # 合理设置点大小
  mytheme +
  ggtitle("(a) 垂直排列(默认)")

p2 <- ggplot(df1, aes(x = 指标, y = 指标值, fill = 指标)) +
  geom_violindot(dots_size = 0.7, binwidth = 0.07, side = "both", orientation = "y") +  # Horizontal orientation
  coord_flip() +  # Flip coordinates for horizontal layout
  mytheme +  # Your custom theme
  ggtitle("(b) 水平排列")
# 组合两个图
gridExtra::grid.arrange(p1, p2, ncol = 2)

6.5 图形观察和代码编写的心得体会

  • 蜂群图(Beeswarm Plot)
    蜂群图通过将数据点以非重叠方式散布在轴上,清晰展现出数据的分布密度与离散程度。相比散点图,它更适合显示小样本或中等样本的数据分布,避免了点重叠。
  • 箱线图 + 蜂群图组合
    箱线图显示了数据的五数概括(最小值、下四分位、中位数、上四分位、最大值),而蜂群图补充了每个个体观测的细节。两者结合,可以兼顾整体趋势与个体差异,非常直观。
  • 威尔金森点图(Dotplot)
    用于展示频数分布,适合展示离散数据。通过 geom_dotplot() 实现时,可选择向上堆叠或居中堆叠两种方式,前者更强调频数高低,后者强调对称分布。
  • 云雨图(Violin Dotplot)
    云雨图是小提琴图与点图的结合体,既展示了数据的核密度估计,又保留了原始点分布,可横向或纵向排列。相比普通箱线图,它更具表现力,也能观察数据分布形态的偏态或多峰。
  • 矩形热图与极坐标热图
    热图是二维频数分布的直观展示,适合观察两个变量间的聚集区。极坐标转换则提供一种创意型表达,尽管解释性略逊,但在数据报告中有较强的视觉冲击力。
  • 标准化处理的重要性
    在绘制比较图(如两个变量在同一坐标轴下)时,进行 scale() 标准化有助于消除量纲差异,使可视化更具可比性。
  • 长数据格式的优势
    多变量统一作图时,使用 pivot_longer() 转换为“长格式”能极大简化绘图逻辑,尤其适合 ggplot2 语法结构。

  • 绘图主题与排版
    使用统一的主题(如 theme_bw()theme_modern())可以保持风格一致,去除图例可避免干扰,同时使用 grid.arrange() 可直观对比多个图形。

  • 图形参数调优
    不同图形函数对点大小(如 size vs dots_size)和宽度(如 binwidth)的敏感性不同,调试过程中需参考文档并适度实验,避免出现图形不出或比例失衡。

  • 包依赖与函数命名冲突
    geom_violindot() 需加载 ggdist 包、theme_modern() 来自 see 包,需事先安装并避免与其他包的函数冲突。