第四章 数据分布可视化

Author

221527106曾乐

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="blue")+
  geom_density(color="blue2",size=0.7)+
  annotate("text",x=2.5,y=0.7,label=paste0("偏度系数=",round(skewness(df$eruptions),4)),size=3)+
  annotate("text",x=2.5,y=0.65,label=paste0("峰度系数=",round(kurtosis(df$eruptions),4)),size=3)+
  geom_vline(xintercept=mean(df$eruptions),linetype="twodash",size=0.6,color="red")+
  annotate("text",x=mean(df$eruptions),y=0.7,label=paste0("均值线=",round(mean(df$eruptions),2)),size=3)+
  geom_point(x=median(df$eruptions),y=0,shape=21,size=4,fill="yellow")+
  annotate("text",x=median(df$eruptions),y=0.1,label="中位数",size=3,color="red3")

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

2.3.1 图形观察心得体会

观察图形时,能直观洞悉数据分布、趋势及变量关系。像复合图可整合多维度信息,色彩等视觉元素引导理解,助于快速把握数据特征。

2.3.2 代码编写心得体会

编写绘图代码,需熟稔工具如ggplot2函数功能,重视数据预处理。同时,要把控图形细节,构建清晰逻辑,按目的有序添加图层与参数,精准传达数据信息。

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(指标值))

p1<-ggplot(df)+aes(x=指标值,y=..density..,fill=指标)+
  geom_histogram(position="identity",color="grey60",alpha=0.5)+
  scale_fill_brewer(palette="Set3")
theme(legend.position = c(0.8,0.8),
      legend.background = element_rect(fill="grey90",color="grey"))+
  ggtitle("(a)原始数据的叠加直方图")
List of 4
 $ legend.background     :List of 5
  ..$ fill         : chr "grey90"
  ..$ colour       : chr "grey"
  ..$ linewidth    : NULL
  ..$ linetype     : NULL
  ..$ inherit.blank: logi FALSE
  ..- attr(*, "class")= chr [1:2] "element_rect" "element"
 $ legend.position       : chr "inside"
 $ legend.position.inside: num [1:2] 0.8 0.8
 $ title                 : chr "(a)原始数据的叠加直方图"
 - attr(*, "class")= chr [1:2] "theme" "gg"
 - attr(*, "complete")= logi FALSE
 - attr(*, "validate")= logi TRUE
p2<-ggplot(df)+aes(x=标准化值,y=..density..,fill=指标)+
  geom_histogram(position="identity",color="grey60",alpha=0.5)+
   scale_fill_brewer(palette="Set3")
theme(legend.position = c(0.8,0.8),
      legend.background = element_rect(fill="grey90",color="grey"))+
  ggtitle("(a)标准化数据的叠加直方图")
List of 4
 $ legend.background     :List of 5
  ..$ fill         : chr "grey90"
  ..$ colour       : chr "grey"
  ..$ linewidth    : NULL
  ..$ linetype     : NULL
  ..$ inherit.blank: logi FALSE
  ..- attr(*, "class")= chr [1:2] "element_rect" "element"
 $ legend.position       : chr "inside"
 $ legend.position.inside: num [1:2] 0.8 0.8
 $ title                 : chr "(a)标准化数据的叠加直方图"
 - attr(*, "class")= chr [1:2] "theme" "gg"
 - attr(*, "complete")= logi FALSE
 - attr(*, "validate")= logi TRUE
grid.arrange(p1,p2,ncol=2)

3.3 镜像直方图代码

df<-data%>%
  mutate(
    std.eruptions=scale(eruptions),
    std.waiting=scale(waiting)
  )

p1<-ggplot(df,aes(x=x))+
  geom_histogram(aes(x=eruptions,y=..density..),fill="red",alpha=0.3,bins=30)+
  geom_label(aes(x=20,y=0.1),label="eruptions",color="red")+
  geom_histogram(aes(x=waiting,y=..density..),fill="blue",alpha=0.3,bins=30)+
  geom_label(aes(x=60,y=0.075),label="waiting",color="blue")+
  xlab("指标值")+ggtitle("(a)原始数据镜像密度图")

p2<-ggplot(df,aes(x=x))+
  geom_histogram(aes(x=std.eruptions,y=..density..),fill="red",alpha=0.3,bins=30)+
  geom_label(aes(x=-0.5,y=0.5),label="eruptions",color="red")+
  geom_histogram(aes(x=std.waiting,y=..density..),fill="blue",alpha=0.3,bins=30)+
  geom_label(aes(x=-0.5,y=-0.5),label="waiting",color="blue")+
  xlab("指标值")+ggtitle("(a)标准化数据镜像密度图")

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

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

3.4.1 图形观察心得体会

观察这组镜像密度图,直观感受到数据标准化前后的显著差异。原始数据图中,能清晰看到 “eruptions” 和 “waiting” 分布跨度不同,数值量级差异明显。而标准化后,二者在同一尺度下对比,分布特征更为清晰,便于分析相对关系。这让我明白图形能有效揭示数据本质,不同呈现方式对理解数据特征至关重要,学会从图形变化中挖掘信息,是洞察数据规律的关键。

3.4.2 代码编写心得体会

在编写绘制此类图形的代码时,深刻体会到数据预处理的关键作用。从原始数据到标准化数据的转换,需精准使用函数确保数据准确归一化。绘图过程中,对ggplot2等绘图包函数的运用,要精确设置参数来呈现理想图形效果,如调整颜色、添加标签等。每一步代码都需严谨对待,从数据准备到图形细节雕琢,都影响最终呈现。这不仅提升了编程技能,更让我懂得代码是实现数据可视化想法的桥梁,需不断打磨优化。

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(指标值))


p1<-ggplot(df)+aes(x=指标值,y=..density..,fill=指标)+
   geom_density(position="identity",color="gray60",alpha=0.5)+
  scale_fill_brewer(palette="Set3")+
   theme(legend.position=c(0.8,0.8),            # 设置图例位置
       legend.background=element_rect(fill="grey90",color="grey"))+       # 移除图例整体边框
   ggtitle("(a) 原始数据的叠加直方图")            # 添加标题


p2<-ggplot(df)+aes(x=指标值,y=..density..,fill=指标)+
   geom_density(position="identity",color="gray60",alpha=0.5)+
  scale_fill_brewer(palette="Set3")+
   theme(legend.position=c(0.8,0.8),            # 设置图例位置
       legend.background=element_rect(fill="grey90",color="grey"))+       # 移除图例整体边框
   ggtitle("(a) 标准化数据的叠加直方图")            # 添加标题

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

4.3 分面核密度图

ggplot(df)+aes(x=指标值,y=..density..,fill=指标)+
  geom_density(position="identity",color="gray60",alpha=0.5)+
  scale_fill_brewer(palette="Set3")+                    # 设置调色板
  facet_wrap(~指标,scale="free")+                # 按指标3列分面
  theme(legend.position=c(0.8,0.8),
        legend.background = element_rect(fill = "grey90",color = "grey"))                       # 设置图例位置

4.4 镜像核密度图

df<-data%>%
  mutate(
    std.eruptions=scale(eruptions),
    std.waiting=scale(waiting)
  )
p_waiting <- ggplot(df, aes(x = std.waiting)) +
  geom_density(fill = "skyblue", alpha = 0.7, color = NA) +  # 原数据
  geom_density(aes(x = -std.waiting), fill = "salmon", alpha = 0.7, color = NA) +  # 镜像数据
  labs(title = "Mirror Density Plot: std.waiting",
       x = "Standardized Waiting Time",
       y = "Density") +
  theme_minimal()

# 2. 对std.eruptions绘制镜像核密度图
p_eruptions <- ggplot(df, aes(x = std.eruptions)) +
  geom_density(fill = "lightgreen", alpha = 0.7, color = NA) +  # 原数据
  geom_density(aes(x = -std.eruptions), fill = "orchid", alpha = 0.7, color = NA) +  # 镜像数据
  labs(title = "Mirror Density Plot: std.eruptions",
       x = "Standardized Eruption Duration",
       y = "Density") +
  theme_minimal()

# 并排显示两个图(需安装patchwork包)
library(patchwork)
p_waiting + p_eruptions

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

4.5.1 图形观察心得体会

观察这两幅镜像密度图,能清晰捕捉到标准化后的 “waiting” 和 “eruption” 数据的分布特征。色彩区分明显的曲线展示了数据的多峰形态,反映出变量取值的集中趋势和离散程度。通过对比,可直观发现不同变量分布的差异与相似之处,这种可视化呈现方式让复杂的数据结构变得易于理解,帮助我从宏观角度把握数据规律,也启发我在分析其他数据时,如何利用图形挖掘潜在信息。

4.5.2 代码编写心得体会

在编写绘制此类图形的代码过程中,我深感数据处理与可视化的紧密关联。从数据导入、标准化处理,到使用绘图函数构建图形,每一步都需精准把控。要熟练掌握绘图工具(如ggplot2 )中函数的参数设置,像调整曲线颜色、透明度、添加坐标轴标签等细节,都直接影响图形的可读性与美观度。这不仅锻炼了我的编程能力,更让我明白代码是将数据转化为直观图形的有力手段,需不断实践优化,才能让数据以更有效的方式呈现。

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 箱线图代码

mytheme<-theme(
  plot.title = element_text(size = 11, hjust = 0.5), 
  axis.title = element_text(size = 10),               
  axis.text = element_text(size = 9),                
  legend.text = element_text(size = 8),
  legend.position = "bottom"
)
# 准备数据
df <- data %>%
  gather(key = "指标", value = "指标值") %>%
  mutate(指标 = fct_inorder(指标))

# 设置调色板(使用Set2的前两种颜色)
palette <- RColorBrewer::brewer.pal(6, "Set2")[1:2]

# 绘制箱线图
ggplot(df, aes(x = 指标, y = 指标值, fill = 指标)) +
  geom_boxplot(alpha = 0.7) +                 # 绘制箱线图并设置透明度
  stat_summary(fun = "mean", geom = "point",  # 添加均值点
               shape = 21, size = 2.5, fill = "white") +
  scale_fill_manual(values = palette) +      # 设置填充颜色
  labs(
    title = "火山喷发数据箱线图",
    x = "变量",
    y = "值"
  ) +
  mytheme                                

5.3 小提琴图代码

  • 通过d3r::d3_nest将数据框转化为层次数据“d3.js”作为绘图输入
ggplot(data = df, aes(x = 指标, y = 指标值, fill = 指标)) +
  geom_violin(alpha = 0.7) +
  geom_boxplot(width = 0.1, alpha = 0.7) +
  geom_point(alpha = 0.3, size = 1) +
  stat_summary(fun = "mean", geom = "point",  
               shape = 21, size = 2.5, fill = "white") +
  scale_fill_manual(values = palette) +
  labs(
    title = "火山喷发数据小提琴图",
    x = "变量",
    y = "值"
  ) +
  mytheme

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

5.4.1 图形观察心得体会

观察火山喷发数据的小提琴图和箱线图,能直观感受到两种图形在展示数据分布特征上的独特之处。小提琴图通过其独特的形状,既展示了数据的分布密度,又融合了箱线图的特征,能清晰看到 “eruptions” 和 “waiting” 变量数据的集中趋势、离散程度以及分布形态 。箱线图则以简洁明了的方式,通过箱体、 whiskers(须)和离群点,呈现出数据的四分位数和数据范围。对比这两幅图,让我更深刻理解到不同可视化方式如何从不同角度剖析数据,帮助我们挖掘数据背后的信息,为数据分析和解读提供了多元化的视角。

5.4.2 代码编写心得体会

在编写绘制这两类图形的代码过程中,我充分认识到ggplot2等绘图工具的强大与灵活。从数据的准备与导入,到使用特定函数(如geom_violin绘制小提琴图、geom_boxplot绘制箱线图 )来构建图形,每一步都需要对函数参数进行精细调整。例如调整图形颜色、添加坐标轴标签和标题等细节,这些看似微小的操作却对图形的最终呈现效果有着重要影响。同时,代码编写过程也要求对数据结构和变量关系有清晰的认识,才能准确无误地将数据转化为直观的可视化图形。这不仅提升了我的编程技能,更让我明白代码是实现数据可视化创意的有力工具,需要不断实践和优化,才能更好地服务于数据分析与展示。

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 威尔金森点图代码

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

mytheme<-theme_bw()+theme(legend.position="none")

data_scaled <- as.data.frame(scale(data))
df_long <- tidyr::pivot_longer(
 data_scaled, 
  cols = c("eruptions", "waiting"), 
  names_to = "variable", 
  values_to = "value"
)

# 居中堆叠点图(分变量展示)
ggplot(df_long, aes(x = variable, y = value)) +
  geom_dotplot(
    binaxis = "y",          # 沿y轴分箱
    bins = 30,              # 分箱数30
    dotsize = 0.3,          # 点大小
    stackdir = "center",    # 居中堆叠
    fill = "#66C2A5"        # 填充颜色(Set2调色板第一种)
  ) +
  labs(
    title = "威尔金森点图(居中堆叠)",
    x = "变量",
    y = "标准化值"
  ) +
  mytheme  # 应用自定义主题

6.3 蜂群图代码

mytheme<-theme_bw()+theme(legend.position="none")

df_long <- tidyr::pivot_longer(
  data_scaled, 
  cols = c("eruptions", "waiting"), 
  names_to = "variable", 
  values_to = "value"
)

# 不带箱线图的蜂群图
ggplot(df_long, aes(x = variable, y = value)) +
  geom_beeswarm(
    cex = 0.8,          # 点大小缩放
    shape = 21,         # 带填充的圆形
    size = 0.8,         # 点大小
    fill = "#66C2A5",   # 填充颜色(Set2调色板第一种)
    color = "black"     # 边框颜色
  ) +
  labs(
    title = "蜂群图(不带箱线图)",
    x = "变量",
    y = "标准化值"
  ) +
  mytheme  # 应用自定义主题

6.4 云雨图代码

library(see)  # 提供主题函数theme_modern
mytheme<-theme_modern()+
         theme(legend.position="none",
               plot.title=element_text(size=14,hjust=0.5))   # 调整标题位置

df_long <- tidyr::pivot_longer(
  data_scaled, 
  cols = c("eruptions", "waiting"), 
  names_to = "variable", 
  values_to = "value"
)

# 纵向云雨图
ggplot(df_long, aes(x = variable, y = value, fill = variable)) +
  geom_violindot(
    dots_size = 0.7,      # 点大小
    binwidth = 0.07,      # 分箱宽度
    alpha = 0.7,          # 透明度
    draw_quantiles = 0.5  # 显示中位数
  ) +
  scale_fill_manual(values = c("#66C2A5", "#FC8D62")) +  # Set2调色板前两种颜色
  labs(
    title = "纵向云雨图",
    x = "变量",
    y = "标准化值"
  ) +
  mytheme  # 应用自定义主题

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

6.5.1 图形观察心得体会

观察这些图形,能直观感受到不同可视化方式对展示数据分布的独特作用。纵向云雨图巧妙结合小提琴图与点图元素,既呈现了数据的分布密度,又展示了具体数据点的位置,让我清晰洞察 “eruptions” 和 “waiting” 变量的分布特征。蜂群图(不带箱线图)通过点的分布形态,直观展示数据的集中与离散情况,点的聚集程度能快速反映数据的集中趋势。威尔金森点图(居中堆叠)以独特的堆叠方式,展示数据在不同区间的分布频次,有助于理解数据的层次结构。通过对比这些图形,我认识到选择合适的可视化方式对准确解读数据至关重要,不同图形从不同角度揭示数据内涵,为深入分析提供了多元视角。

6.5.2 代码编写心得体会

在编写绘制这些图形的代码时,我深刻体会到数据可视化过程中编程的严谨性与灵活性。从数据的预处理,如标准化处理,到使用不同绘图函数构建图形,每一步都需要精确把控。以ggplot2为例,使用geom_violindot绘制云雨图、geom_beeswarm绘制蜂群图、geom_dotplot绘制威尔金森点图等,需要熟悉各函数的参数设置,包括点的大小、颜色、位置调整等细节,这些细节决定了图形的最终呈现效果。同时,代码编写过程也是对数据理解的深化过程,只有清晰把握数据结构和变量关系,才能编写出高效、准确的绘图代码。这一系列图形的绘制,不仅提升了我的编程技能,更让我明白代码是实现数据可视化创意的有力工具,需要不断探索和实践,才能更好地用图形讲述数据故事。