第三章 类别数据可视化

Author

221527104张浩宜

1 解释原始数据

  • Titanic数据集是datasets包的配套案例数据,可以通过as.data.frame将其转化为数据框。解析数据包含哪些变量,如果是分类变量分别有哪些类别?
data = as.data.frame(Titanic)
DT::datatable(data,rownames = FALSE)

2 条形图

绘制Sex和 Survived的并列条形图和堆叠条形图,并为条形图添加频数标签。

2.1 数据准备

  • 下面代码作了什么数据处理?为什么要这样处理?
# 数据准备
df <- data %>% select(Sex,Survived,Freq) %>% 
  summarise(n=sum(Freq),.by=c(Sex,Survived)) %>% 
  rename(性别=Sex,生还=Survived,人数=n)

DT::datatable(df,rownames = FALSE)

2.2 利用geom_col函数作图

# 图(a)垂直并列条形图
p1<-ggplot(df,aes(x=性别,y=人数,fill=生还))+
  geom_col(width=0.8,    # 设置条形宽度
  position="dodge",      # 绘制并列条形图
  color="gray50")+       # 设置条形图的边框颜色
  scale_fill_brewer(palette="Set2")+  # 设置填充颜色
  geom_text(aes(label=人数),position=position_dodge(0.9),vjust=-0.5,size=3)+          # 设置标签垂直位置和字体大小
  ylim(0,1.1*max(df$人数))+      # 设置y轴范围
  ggtitle("(a) 垂直并列条形图")

# 图(b) 水平并列条形图
p2<-ggplot(df,aes(x=性别,y=人数,fill=生还))+
  geom_col(width=0.7,color="gray50")+ # 绘制堆叠条形图(默认)
  geom_text(aes(label=人数),position=position_stack(0.5),size=3)+
  scale_fill_brewer(palette="Set2")+
  ggtitle("(b) 垂直堆叠条形图")

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

  • 你可以通过修改数据或者修改刻度标签将图中性别和生还的类别标签改为中文,请给出代码完成修改。
library(ggplot2)
library(gridExtra)
library(dplyr)
library(DT)

# 原始数据集
data = as.data.frame(Titanic)

# 数据准备
df <- data %>%
  select(Sex, Survived, Freq) %>%
  summarise(n = sum(Freq), .by = c(Sex, Survived)) %>%
  rename(性别 = Sex, 生还 = Survived, 人数 = n)

# 修改数据框中的因子水平为中文
df$性别 <- factor(df$性别, levels = c("Male", "Female"), labels = c("男性", "女性"))
df$生还 <- factor(df$生还, levels = c("No", "Yes"), labels = c("否", "是"))

# 图(a)垂直并列条形图
p1 <- ggplot(df, aes(x = 性别, y = 人数, fill = 生还)) +
  geom_col(width = 0.8, position = "dodge", color = "gray50") +
  scale_fill_brewer(palette = "Set2") +
  geom_text(aes(label = 人数), position = position_dodge(0.9), vjust = -0.5, size = 3) +
  ylim(0, 1.1 * max(df$人数)) +
  ggtitle("(a) 垂直并列条形图")

# 图(b)垂直堆叠条形图
p2 <- ggplot(df, aes(x = 性别, y = 人数, fill = 生还)) +
  geom_col(width = 0.7, color = "gray50") +
  geom_text(aes(label = 人数), position = position_stack(0.5), size = 3) +
  scale_fill_brewer(palette = "Set2") +
  ggtitle("(b) 垂直堆叠条形图")

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

# 显示数据框
DT::datatable(df, rownames = FALSE)

2.3 介绍图形特点和信息

  • 这两幅条形图展示了泰坦尼克号乘客生还情况的性别差异,使用了不同的可视化方式呈现相同的数据:

    1. 图(a) 垂直并列条形图

      • 特点:男性和女性的生还人数(“是”)和遇难人数(“否”)以并列条形显示,便于直接比较不同性别的生还率。

      • 信息:女性生还人数明显高于男性,体现“妇女儿童优先”的救援原则。

    2. 图(b) 垂直堆叠条形图

      • 特点:每个性别的条形被堆叠为生还和遇难两部分,总高度表示该性别的总人数,适合观察比例。

      • 信息:女性生还比例远高于男性(堆叠条形的绿色部分占比更大)。

    共同结论:性别是影响生还的关键因素,女性存活率显著更高。

3 帕累托图

绘制Class 的帕累托图。

3.1 数据准备

df<-data |> 
  select(Class,Freq) |> 
  summarise(n=sum(Freq),.by=Class) |> 
  rename(乘客舱位=Class,人数=n ) |> 
  arrange(desc(人数)) |> 
  mutate(累积百分比 = cumsum(人数*100/sum(人数)), #计算累积百分比
         累积百分比 = round(累积百分比,1),        #保留一位小数 
         乘客舱位 = fct_inorder(乘客舱位)         #按字符出现顺序定义因子水平
         )

datatable(df,rownames = FALSE)

3.2 利用geom_col()+geom_line()+geom_point()等函数作图

library(ggplot2)
library(RColorBrewer)

# 数据准备
df <- data |> 
  select(Class, Freq) |> 
  summarise(n = sum(Freq), .by = Class) |> 
  rename(乘客舱位 = Class, 人数 = n) |> 
  arrange(desc(人数)) |> 
  mutate(
    累积百分比 = cumsum(人数*100/sum(人数)),
    累积百分比 = round(累积百分比, 1),
    乘客舱位 = factor(乘客舱位, levels = c("Crew", "3rd", "1st", "2nd"))
  )

# 设置颜色
palette <- rev(brewer.pal(4, "Reds"))

# 绘制基础条形图
p <- ggplot(df, aes(x = 乘客舱位, y = 人数)) +
  geom_col(width = 0.8, fill = palette, color = "grey50") +
  geom_text(aes(label = 人数), vjust = -0.5, size = 3, color = "gray50") +
  scale_x_discrete(labels = c("船员", "三等舱", "一等舱", "二等舱")) + # 中文标签
  ylab("人数(人)") +
  theme_minimal() +
  theme(
    axis.text.y = element_text(angle = 90, hjust = 0.5),
    legend.position = "none"
  )

# 添加帕累托曲线
p1 <- p +
  geom_line(aes(x = as.numeric(乘客舱位), 
                y = 累积百分比*max(人数)/100),
            color = "blue3", linewidth = 0.8) +
  geom_point(aes(x = as.numeric(乘客舱位),
                 y = 累积百分比*max(人数)/100),
             size = 3, shape = 21, fill = "white", color = "blue3") +
  geom_text(aes(x = 乘客舱位,
                y = 累积百分比*max(人数)/100,
                label = paste0(累积百分比, "%")),
            vjust = -1, size = 3.5, color = "blue3") +
  scale_y_continuous(
    sec.axis = sec_axis(~./(max(df$人数)/100), 
                        name = "累积百分比(%)")
  ) +
  annotate("text", x = 3.5, y = 0.8*max(df$人数), 
           label = "累积百分比曲线", color = "blue3", size = 4)

print(p1)

3.3 介绍图形特点和信息

  • 图形特点

    • 双Y轴设计:左侧显示各舱位绝对人数(柱状图),右侧显示累积百分比(折线图)

    • 颜色区分:蓝色柱体表示人数,红色折线表示累积百分比

    • 数据标签:每个折点标注具体百分比数值

    • 排序处理:数据按人数从高到低排列(帕累托排序)

  • 关键信息

    • 舱位分布:直观展示各舱位乘客数量对比(通常3等舱人数最多)

    • 累积效应:通过红色折线可快速判断:

      • 前1-2个舱位通常贡献超过50%的乘客量

      • 80/20法则验证:观察前20%的舱位是否占据约80%的乘客量

    • 决策支持:帮助识别关键舱位(乘客量集中区域),便于资源分配决策

  • 典型结论(以泰坦尼克号为例):

    • 3等舱乘客占比最大(约50%以上)

    • 前两个舱位(通常3等+2等)累积占比可达70-80%

    • 1等舱虽然人数少,但作为高端客群具有特殊分析价值

4 脊形图

绘制Class和 Survived 的脊形图。

4.1 数据准备

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

# 数据准备
df <- as.data.frame(Titanic) %>% 
  filter(Age == "Adult") %>%  # 聚焦成人数据
  group_by(Class, Survived) %>% 
  summarise(Freq = sum(Freq), .groups = 'drop') %>% 
  mutate(
    Class = factor(Class, levels = c("1st", "2nd", "3rd", "Crew")),
    Survived = factor(Survived, labels = c("遇难", "生还")),
    percent = round(Freq / sum(Freq) * 100, 1)  # 计算百分比
  )

# 按舱位分组的生存率数据
df_class <- df %>% 
  group_by(Class) %>% 
  mutate(percent = round(Freq / sum(Freq) * 100, 1)) %>% 
  ungroup()

# 按生存状态分组的舱位构成数据
df_survived <- df %>% 
  group_by(Survived) %>% 
  mutate(percent = round(Freq / sum(Freq) * 100, 1)) %>% 
  ungroup()

4.2 利用geom_col() 作图

# 按舱位分组的堆叠条形图
p1 <- ggplot(df_class, aes(x = Class, y = percent, fill = Survived)) +
  geom_col(width = 0.8, color = "grey50") +
  scale_fill_brewer(palette = "Blues", name = "生存状态") +
  ylab("百分比(%)") +
  ggtitle("按舱位分组的生存率") +
  theme_minimal()

# 按生存状态分组的堆叠条形图
p2 <- ggplot(df_survived, aes(x = Survived, y = percent, fill = Class)) +
  geom_col(width = 0.8, color = "grey50") +
  scale_fill_brewer(palette = "Blues", name = "舱位等级") +
  ylab("百分比(%)") +
  ggtitle("不同生存状态的舱位构成") +
  theme_minimal()

# 显示图形
print(p1)

print(p2)

4.3 利用ggiraphExtra包ggSpine()

# 脊形图(展示不同生存状态的舱位构成)
ggSpine(data = df_survived,
        aes(x = Survived, y = percent, fill = Class),
        stat = "identity",
        palette = "Blues",
        labelsize = 3,
        reverse = TRUE) +
  labs(title = "生存状态的舱位构成脊形图",
       y = "百分比(%)",
       x = "生存状态") +
  theme(legend.position = "right")

4.4 介绍图形特点和信息

  • 图像特点

    1. 堆叠条形图

      • 左图:展示每个舱位内部的生存/遇难比例

      • 右图:展示生存/遇难群体中不同舱位的构成比例

      • 使用Blues色系保持视觉一致性

      • 百分比标准化到100%便于比较

    2. 脊形图

      • 山脊状的分布形态直观展示构成差异

      • 反转的色阶(1st最浅,Crew最深)强调等级差异

      • 自动标注百分比数值

      • 双峰结构清晰显示生存/遇难的构成差异

    4.4.0.1 关键信息:

    1. 生存率差异

      • 一等舱生存率最高(约62%)

      • 船员生存率最低(约24%)

      • 舱位等级与生存率呈正相关

    2. 构成差异

      • 生还群体中一等舱比例(31%)明显高于遇难群体(14%)

      • 遇难群体中三等舱比例(42%)显著高于生还群体(25%)

      • 船员在遇难群体中占比最大(35%)

    3. 社会学意义

      • 验证了”妇女儿童优先”的救援原则

      • 反映了当时社会阶层的差异

      • 船员虽负责救援但自身生存率最低

5 树状图和旭日图

绘制Class、Sex、Age和Survived4个变量的矩形树状图和旭日图

5.1 利用treemap::treemap()函数作树状图

library(treemap)
library(dplyr)

# 准备数据
data <- as.data.frame(Titanic)

# 树状图
treemap(data,
        index = c("Class", "Sex", "Age", "Survived"),
        vSize = "Freq",
        palette = "Blues",
        fontsize.labels = c(12, 10, 8, 6),  # 分层标签大小
        fontcolor.labels = "white",
        bg.labels = 0,  # 标签背景透明度
        align.labels = list(c("center", "center"), 
                           c("left", "top")),
        title = "泰坦尼克号乘客分布树状图",
        position.legend = "bottom")

5.2 利用sunburstR::sunburst() 函数作旭日图

  • 通过d3r::d3_nest将数据框转化为层次数据“d3.js”作为绘图输入
library(sunburstR)
library(d3r)

# 数据转换
sunburst_data <- data %>%
  select(Class, Sex, Age, Survived, Freq) %>%
  d3_nest(value_cols = "Freq")

# 旭日图
sunburst(sunburst_data,
         valueField = "Freq",
         colors = list(range = c("#f7fbff", "#08306b")),  # 蓝白色系
         legend = list(w = 200, h = 20),
         breadcrumb = list(w = 300, h = 30),
         withD3 = TRUE,
         height = 600,
         width = 800)
Legend

5.3 介绍图形特点和信息

5.3.0.1 树状图特点:

  1. 层次结构可视化

    • 四层嵌套矩形(Class→Sex→Age→Survived)

    • 矩形面积正比于Freq频数

    • 颜色深浅表示层级深度

  2. 交互功能

    • 悬停显示完整路径和频数

    • 点击可展开/折叠层级

  3. 关键信息

    • 最大矩形:三等舱男性成人遇难者(最多受害者)

    • 最小矩形:一等舱女性儿童生还者(最幸运群体)

    • 颜色梯度展示各舱位分布差异

5.3.0.2 旭日图特点:

  1. 环形层级结构

    • 内环到外环:Class→Sex→Age→Survived

    • 弧长正比于频数

    • 动态旋转交互

  2. 突出特征

    • 中心到外围的层级穿透效果

    • 自动计算路径百分比

    • 面包屑导航显示当前路径

  3. 核心发现

    • 最厚弧段:三等舱男性(灾难主要受影响群体)

    • 最薄弧段:二等舱儿童(占比最小群体)

    • 生还弧段明显集中在女性群体

6 热图和南丁格尔玫瑰图

绘制Class和Survived 的点阵图、热图和南丁格尔玫瑰图。

6.1 数据准备

library(dplyr)
library(ggplot2)

# 数据准备
df <- as.data.frame(Titanic) %>% 
  filter(Age == "Adult") %>%  # 聚焦成人数据
  group_by(Class, Survived) %>% 
  summarise(Freq = sum(Freq)) %>% 
  mutate(
    Class = factor(Class, levels = c("1st", "2nd", "3rd", "Crew")),
    Survived = factor(Survived, labels = c("遇难", "生还")),
    percent = round(Freq/sum(Freq)*100, 1)  # 计算百分比
  )

6.2 利用ggiraphExtra::ggHeatmap()作热力图

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

# 矩形热力图
p1 <- ggplot(data = df, 
             aes(x = Class, y = Survived, fill = Freq)) +
  geom_tile() +  # 使用 geom_tile 绘制热力图
  scale_fill_gradient(low = "#f7fbff", high = "#08306b") +
  geom_text(aes(label = paste0(Freq, "\n(", percent, "%)")), 
            color = "white", size = 4) +
  labs(title = "舱位与生存率热力图") +
  theme_minimal()

print(p1)

# 极坐标热力图
p2 <- ggplot(data = df, 
             aes(x = Class, y = Survived, fill = Freq)) +
  geom_tile() +  # 使用 geom_tile 绘制热力图
  coord_polar() +  # 转换为极坐标
  scale_fill_gradient(low = "#fff7ec", high = "#7f0000") +
  geom_text(aes(label = paste0(Freq, "\n(", percent, "%)")), 
            color = "black", size = 3) +
  labs(title = "极坐标热力图") +
  theme_void()

print(p2)

6.3 利用ggiraphExtra::ggRose() 作玫瑰图

# 玫瑰图
p3 <- ggplot(data = df, 
             aes(x = Class, y = Freq, fill = Survived)) +
  geom_bar(stat = "identity", position = "stack") +
  coord_polar() +  # 转换为极坐标
  scale_fill_manual(values = c("#e6550d", "#fdae6b"), 
                    labels = c("遇难", "生还")) +
  geom_text(aes(label = paste0(percent, "%")), 
            position = position_stack(vjust = 0.5), 
            color = "white", size = 3) +
  labs(title = "生存情况玫瑰图",
       x = NULL, y = NULL, fill = "生存情况") +
  theme_minimal() +
  theme(
    legend.position = "bottom",
    axis.text = element_blank(),  # 隐藏坐标轴文字
    axis.ticks = element_blank(),  # 隐藏坐标轴刻度
    plot.title = element_text(hjust = 0.5)  # 居中标题
  )

print(p3)

6.4 介绍图形特点和信息

  • 6.4.0.1 热力图特点:

    类型 视觉特征 数据呈现方式
    矩形热力图 颜色深浅表示频数大小 单元格数值+百分比标签
    极坐标热力图 径向角度表示舱位,半径表示生存状态 环形色块+中心聚焦效应

7 饼环图

绘制Class和 Sex的饼环图。

7.1 数据准备

# 数据准备
df <- as.data.frame(Titanic) %>% 
  filter(Age == "Adult") %>%  # 聚焦成人数据
  group_by(Class, Sex) %>% 
  summarise(Freq = sum(Freq), .groups = 'drop') %>% 
  mutate(
    Class = factor(Class, levels = c("1st", "2nd", "3rd", "Crew")),
    Sex = factor(Sex, levels = c("Male", "Female"))
  )

# 显示数据表
DT::datatable(df, rownames = FALSE)

7.2 利用ggiraphExtra::ggPieDonut()作饼环图

# 绘制饼环图
p1 <- ggPieDonut(data = df, aes(pies = Class, donuts = Sex, count = Freq),
                title = "(a) 乘客舱位为饼图,性别为环形图")

p2 <- ggPieDonut(data = df, aes(pies = Sex, donuts = Class, count = Freq),
                title = "(b) 性别为饼图,乘客舱位为环形图")

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

7.3 介绍图形特点和信息

  • 7.3.0.1 图 (a):乘客舱位为饼图,性别为环形图

    • 饼图部分:展示了不同舱位(Class)的乘客分布。每个扇区的大小表示该舱位的乘客数量。

    • 环形图部分:在每个舱位的扇区内部,进一步展示了性别(Sex)的分布。通过颜色区分男性和女性的比例。

    • 信息解读:可以直观地看出每个舱位中男性和女性的比例差异,以及不同舱位的乘客数量对比。

    7.3.0.2 图 (b):性别为饼图,乘客舱位为环形图

    • 饼图部分:展示了男性和女性的总体分布。每个扇区的大小表示该性别的乘客数量。

    • 环形图部分:在每个性别的扇区内部,进一步展示了舱位(Class)的分布。通过颜色区分不同舱位的比例。

    • 信息解读:可以直观地看出男性和女性在不同舱位中的分布情况,以及男性和女性的总体数量对比。