第三章 类别数据可视化

Author

kaka

1 解释原始数据

  • Titanic数据集是datasets包的配套案例数据,可以通过as.data.frame将其转化为数据框。解析数据包含哪些变量,如果是分类变量分别有哪些类别?
data = as.data.frame(Titanic)
DT::datatable(data,rownames = FALSE)
变量名 类别(Levels) 说明
Survived No, Yes 是否幸存(因变量)
Pclass 1st, 2nd, 3rd 船舱等级(1等为最高级)
Sex Male, Female 乘客性别
Age Child, Adult 年龄分组(部分数据集)
Embarked Cherbourg, Queenstown, Southampton 登船港口(C/Q/S)

2 条形图

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

ggplot(data, aes(x = Sex, y = Freq, fill = Survived)) +
  geom_bar(stat = "identity", position = position_dodge()) +  # 并列效果
  geom_text(aes(label = Freq), 
            position = position_dodge(width = 0.9), 
            vjust = -0.5, size =3 ) +  # 添加频数标签
  labs(title = "Titanic Survival by Sex (Side-by-side)",
       x = "Sex", y = "Count", fill = "Survived") +
  theme_minimal()

ggplot(data, aes(x = Sex, y = Freq, fill = Survived)) +
  geom_bar(stat = "identity") +  # 默认堆叠效果
  geom_text(aes(label = Freq), 
            position = position_stack(vjust = 0.5),  # 标签居中堆叠部分
            size = 4, color = "white") +  # 白色标签提高对比度
  labs(title = "Titanic Survival by Sex (Stacked)",
       x = "Sex", y = "Count", fill = "Survived") +
  theme_minimal()

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) 

  • 你可以通过修改数据或者修改刻度标签将图中性别和生还的类别标签改为中文,请给出代码完成修改。
# 使用 scale_x_discrete 和 scale_fill_discrete 修改标签
p1 <- ggplot(df, aes(x = 性别, y = 人数, fill = 生还)) +
  geom_col(width = 0.8, position = "dodge", color = "gray50") +
  scale_fill_brewer(
    palette = "Set2",
    labels = c("No" = "未生还", "Yes" = "生还")  # 修改图例标签
  ) +
  scale_x_discrete(
    labels = c("Male" = "男性", "Female" = "女性")  # 修改x轴标签
  ) +
  geom_text(aes(label = 人数), position = position_dodge(0.9), vjust = -0.5, size = 3) +
  ylim(0, 1.1 * max(df$人数)) +
  ggtitle("(a) 垂直并列条形图")

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

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

2.3 介绍图形特点和信息

  • 特点:(a)

    • 并列对比:男性和女性的生还/未生还人数并排显示,便于直接比较。

    • 颜色区分:使用 Set2 调色板(fill=生还),生还(Yes)和未生还(No)用不同颜色区分。

    • 标签清晰:每个条形顶部标注具体人数,避免视觉误差。

    • Y轴扩展ylim(0, 1.1*max) 扩展了纵轴范围,防止标签溢出。

    传达信息

    • 女性生还人数显著高于男性(符合“妇孺优先”历史背景)。

    • 男性未生还人数远高于女性,体现性别差异对生存率的影响。

      (b)

    • 特点

      • 堆叠展示:每个性别条形的总高度=生还+未生还人数,体现构成比例。

      • 内部标签:人数标签居中堆叠部分,白色文字增强对比度(需手动设置 color="white")。

      • 统一配色:与图(a)一致,保持视觉连贯性。

      信息

      • 女性条形的“生还”部分占比更大,男性反之。

      • 可直观看出各性别的生还率差异(需结合具体数值)。

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()等函数作图

df <- df |> 
  arrange(desc(人数))

# 创建帕累托图
ggplot(df, aes(x = fct_inorder(乘客舱位))) +  # 按当前顺序固定因子水平
  # 柱状图部分 - 表示各类别人数
  geom_col(aes(y = 人数), fill = "steelblue", width = 0.7) +
  # 折线图部分 - 表示累积百分比
  geom_line(aes(y = 累积百分比 * max(人数) / 100, group = 1), 
            color = "red", size = 1) +
  # 点部分 - 突出显示累积百分比点
  geom_point(aes(y = 累积百分比 * max(人数) / 100), 
             color = "red", size = 3) +
  # 添加右侧y轴(累积百分比)
  scale_y_continuous(
    name = "人数",
    sec.axis = sec_axis(~ . * 100 / max(df$人数), 
                       name = "累积百分比(%)",
                       labels = scales::percent_format(scale = 1))
  ) +
  # 添加标签和标题
  labs(
    title = "乘客舱位帕累托图",
    subtitle = "柱状图表示人数,折线图表示累积百分比",
    x = "乘客舱位",
    caption = "数据来源: 泰坦尼克号数据集"
  ) +
  # 自定义主题
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1),
    plot.title = element_text(hjust = 0.5, face = "bold"),
    plot.subtitle = element_text(hjust = 0.5),
    panel.grid.major.x = element_blank()
  ) +
  # 添加80%参考线
  geom_hline(yintercept = 0.8 * max(df$人数), 
             linetype = "dashed", color = "darkgreen") +
  annotate("text", x = nrow(df)/2, y = 0.82 * max(df$人数), 
           label = "80% 参考线", color = "darkgreen")

3.3 介绍图形特点和信息

  • 3.3.1 柱状图(geom_col()

    • 表示各舱位的乘客人数,柱子的高度代表该舱位的乘客数量。

    • 按降序排列(从高到低),便于直观比较各舱位的重要性。

    • 颜色:通常使用蓝色或其他醒目的颜色,增强可视化效果。

    3.3.2 (2) 累积百分比折线图(geom_line() + geom_point()

    • 表示各舱位的累积百分比,从第一个舱位开始逐步累加,最终达到100%。

    • 折线:连接各数据点,表示累积趋势。

    • 数据点(geom_point():突出显示每个舱位的累积百分比值。

    • 颜色:通常使用红色,与柱状图形成对比。

    3.3.3 (3) 双Y轴(scale_y_continuous(sec.axis = ...)

    • 左侧Y轴:表示人数(柱状图的单位)。

    • 右侧Y轴:表示累积百分比(0%~100%),与折线图对应。

    3.3.4 (4) 80% 参考线(geom_hline()

    • 水平虚线:标记80%的位置,用于判断哪些舱位贡献了80%的乘客。

    • 帕累托法则(80/20法则):通常前20%的因素(舱位)贡献了80%的影响(乘客数)。

4 脊形图

绘制Class和 Survived 的脊形图。

4.1 数据准备

df <- as.data.frame(Titanic) %>%
  filter(Class != "Crew") %>%  # 可选:移除船员数据
  group_by(Class, Survived) %>%
  summarise(Count = sum(Freq), .groups = "drop") %>%
  mutate(Percentage = Count / sum(Count) * 100)

4.2 利用geom_col() 作图

ggplot(df, aes(x = Class, y = Percentage, fill = Survived)) +
  geom_col(position = "stack", width = 0.7, alpha = 0.8) +
  geom_text(aes(label = paste0(round(Percentage, 1), "%")),
            position = position_stack(vjust = 0.5),
            color = "white", size = 3.5) +
  scale_fill_manual(
    values = c("Yes" = "#1b9e77", "No" = "#d95f02"),
    labels = c("Yes" = "幸存", "No" = "遇难")
  ) +
  labs(
    title = "泰坦尼克号各舱位乘客生存情况",
    subtitle = "使用堆叠柱状图展示生存分布",
    x = "乘客舱位",
    y = "百分比(%)",
    fill = "生存状态"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    plot.subtitle = element_text(hjust = 0.5),
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = "top"
  ) +
  coord_flip()  # 翻转坐标轴,使图表更像脊形图

4.3 利用ggiraphExtra包ggSpine()

4.4 介绍图形特点和信息

5 树状图和旭日图

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

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

data(Titanic)
df <- as.data.frame(Titanic) %>% 
  filter(Class != "Crew") %>%  # 可选:移除船员数据
  group_by(Class, Sex, Age, Survived) %>% 
  summarise(Freq = sum(Freq), .groups = "drop") %>% 
  mutate(
    Survived = ifelse(Survived == "Yes", "幸存", "遇难"),
    # 创建组合标签用于显示
    label = paste(Class, Sex, Age, Survived, sep = " | ")
  )
# 绘制矩形树状图
treemap(
  df,
  index = c("Class", "Sex", "Age", "Survived"),  # 分层变量
  vSize = "Freq",                               # 方块大小依据
  vColor = "Freq",                              # 颜色深浅依据
  type = "value",                               # 按数值着色
  title = "泰坦尼克号乘客分布矩形树状图",
  fontsize.title = 14,
  palette = "RdYlBu",                           # 红-黄-蓝渐变色
  border.col = "white",                         # 边框颜色
  border.lwds = 0.5,                            # 边框粗细
  fontsize.labels = c(12, 10, 8, 6),            # 各层标签字号
  align.labels = list(c("center", "center"),    # 标签对齐方式
                      c("left", "top"), 
                      c("right", "bottom")),
  inflate.labels = TRUE                         # 允许标签扩展
)

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

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

    # 使用泰坦尼克号数据
    data(Titanic)
    df <- as.data.frame(Titanic) %>% 
      filter(Class != "Crew") %>%  # 移除船员数据
      uncount(Freq) %>%           # 展开为个体观测数据
      mutate(
        Class = factor(Class, levels = c("1st", "2nd", "3rd")),
        Survived = ifelse(Survived == "Yes", "幸存", "遇难")
      )
    
    # 转换为d3.js嵌套格式
    df_tree <- df %>%
      d3_nest(
        root = "泰坦尼克号",
        value_cols = "Freq",      # 频数列(需存在)
        json = FALSE              # 返回列表而非JSON
      )
library(sunburstR)
sunburst(
  data = df_tree,
  valueField = "Freq",        # 使用频数字段(原代码中的'地区生产总值'替换为'Freq')
  count = TRUE,               # 显示计数和百分比
  sumNodes = TRUE,            # 显示各层级总和
  colors = list(
    range = c("#66C2A5", "#FC8D62", "#8DA0CB", "#E78AC3"),  # 自定义颜色范围
    domain = c("1st", "2nd", "3rd", "Male", "Female", "Adult", "Child", "幸存", "遇难")
  ),
  breadcrumb = list(w = 200, h = 30, s = 10),  # 路径导航样式
  width = "100%",
  height = 600,
  withD3 = TRUE,             # 启用D3交互功能
  explanation = "function(d) {return d.data.name + ': ' + d.value + '人 (' + (d.value/d.parent.value*100).toFixed(1) + '%)';}"
)
Legend

5.3 介绍图形特点和信息

6 热图和南丁格尔玫瑰图

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

6.1 数据准备

# 使用泰坦尼克号数据
data(Titanic)
df <- as.data.frame(Titanic) %>% 
  filter(Class != "Crew") %>%
  group_by(Class, Survived) %>%
  summarise(Freq = sum(Freq), .groups = "drop") %>%
  mutate(
    Survived = factor(Survived, levels = c("Yes", "No")),
    Class = factor(Class, levels = c("1st", "2nd", "3rd"))
  )

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

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

ggplot(df, aes(x = Survived, y = Class, size = Freq, color = Survived)) +
  geom_point(alpha = 0.7) +
  scale_size_continuous(range = c(5, 15)) +  # 控制点的大小范围
  scale_color_manual(values = c("Yes" = "#1b9e77", "No" = "#d95f02")) +
  labs(
    title = "泰坦尼克号舱位生存情况点阵图",
    x = "生存状态",
    y = "乘客舱位",
    size = "人数",
    color = "生存状态"
  ) +
  theme_minimal() +
  theme(legend.position = "right")

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

# 1. 准备数据(确保包含必需的列)
data(Titanic)
df <- as.data.frame(Titanic) %>% 
  filter(Class != "Crew") %>%
  group_by(Class, Survived) %>%
  summarise(Freq = sum(Freq), .groups = "drop") %>%
  mutate(
    Survived = factor(Survived),
    Class = factor(Class)
  )

# 2. 正确调用ggRose()
ggRose(
  data = df,
  mapping = aes(x = Class, y = Freq, fill = Survived),
  palette = "Paired",  # RColorBrewer标准调色板
  interactive = FALSE
)

6.4 介绍图形特点和信息

  • 热力图

  • 颜色深浅:表示数值大小(如深色=高值,浅色=低值)

  • 二维矩阵:行和列代表两个分类变量(如舱位等级 vs 生存状态)

  • 单元格大小:通常固定,仅通过颜色传递信息

  • 头等舱(1st):绿色较深 → 幸存率高

  • 三等舱(3rd):红色较深 → 死亡人数多

  • 快速发现:舱位等级与生存率呈明显相关性

    6.5 玫瑰图(Rose Chart/Nightingale Chart)

    6.5.1 图形特点

    1. 视觉编码

      • 扇形角度/半径:表示数值大小

      • 颜色:区分次级分类(如生存状态)

      • 极坐标系:数据以环形形式展示

7 饼环图

绘制Class和 Sex的饼环图。

7.1 数据准备

data(Titanic)
df <- as.data.frame(Titanic) %>% 
  filter(Class != "Crew") %>%
  group_by(Class, Sex) %>%
  summarise(Freq = sum(Freq), .groups = "drop")

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

# 绘制Class和Sex的饼环图
plot <- ggPieDonut(
  data = df,
  mapping = aes(pies = Class, donuts = Sex, count = Freq)  # 必须用mapping
)
 
 

print(plot) 

7.3 介绍图形特点和信息

  • 7.3.0.1 视觉结构

    组件 描述
    外层环(Pie) 显示舱位等级(1st/2nd/3rd)的比例,面积大小对应乘客数量
    内层环(Donut) 每个舱位内部分为男(Male)、女(Female)的比例,颜色区分性别
    颜色编码 不同颜色代表不同舱位-性别组合(如1st-Male、1st-Female等)
    交互功能 鼠标悬停显示具体人数和百分比(需interactive=TRUE
  1. 舱位分布

    • 三等舱(3rd)面积最大 → 乘客数量最多

    • 头等舱(1st)面积最小 → 乘客数量最少

    • 头等舱:女性(绿色)占比 > 男性(橙色)
      → 反映当时“妇女儿童优先”的逃生原则

    • 三等舱:男性占比显著更高
      → 符合移民/劳工乘客群体的历史背景