第三章 类别数据可视化

Author

kaka

1 解释原始数据

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

    class("1st""2nd""3rd""Crew")\sex("Male""Female)\age("Child""Adult")\survived("No""Yes")分类变量 freq数值变量

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列组合图形

  • 你可以通过修改数据或者修改刻度标签将图中性别和生还的类别标签改为中文,请给出代码完成修改。
# 图(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) 垂直并列条形图")+
  scale_x_discrete(
    "性别",
    labels=c("男","女")
  )+
  scale_fill_discrete(
    "生还",
    labels=c("否","是")
    )

# 图(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) 垂直堆叠条形图")+
  scale_x_discrete(
   "性别",
    labels=c("男","女")
   )+
  scale_fill_discrete(
   "生还",
    labels=c("否","是")
   )

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

2.3 介绍图形特点和信息

  • 图a直观展示不同性别的生还情况

  • 图b展示不同性别之间生还比例和总体人数

3 帕累托图

绘制Class 的帕累托图。

3.1 数据准备

library(ggplot2)
library(dplyr)
library(forcats)

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

# 创建主图形(条形图 + 折线图/点图)
pareto <- ggplot(df, aes(x = 乘客舱位)) +
  # 条形图(频数)
  geom_col(aes(y = 人数, fill = 乘客舱位), 
           width = 0.7, 
           alpha = 0.8) +
  # 折线图(累积百分比,右侧y轴)
  geom_line(aes(y = 累积百分比 * max(人数) / 100, group = 1), 
            color = "red", 
            linewidth = 1) +
  # 点图(标记累积百分比)
  geom_point(aes(y = 累积百分比 * max(人数) / 100), 
             color = "red", 
             size = 3) +
  # 左侧y轴(频数)
  scale_y_continuous(
    name = "人数",
     # 右侧y轴
  ) +
  # 自定义填充颜色
  scale_fill_brewer(palette = "Set2") +
  # 添加数据标签
  geom_text(aes(y = 人数, label = 人数), 
            vjust = -0.5, 
            size = 4) +
  geom_text(aes(y = 累积百分比 * max(人数) / 100, label = paste0(累积百分比, "%")),
            vjust = -1, 
            size = 4, 
            color = "red") +
  # 主题调整
  labs(title = "泰坦尼克号乘客舱位帕累托图",
       x = "乘客舱位",
       fill = "舱位") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))  # 倾斜x轴标签

print(pareto)

3.3 介绍图形特点和信息

  • 能够直观展示不同舱位的人数和累积百分比

4 脊形图

绘制Class和 Survived 的脊形图。

4.1 数据准备

library(dplyr)  # 加载dplyr包
library(ggplot2)

# 数据预处理
df <- as.data.frame(Titanic) %>%
  group_by(Class, Survived) %>%
  summarise(人数 = sum(Freq), .groups = "drop") %>%
  mutate(
    Class = factor(Class, levels = c("1st", "2nd", "3rd", "Crew")),  # 固定舱位顺序
    Survived = factor(Survived, labels = c("未生还", "生还"))         # 修改生还标签为中文
  )

4.2 利用geom_col() 作图

ggplot(df, aes(x = Class, y = 人数, fill = Survived)) +
  geom_col(width = 0.7, color = "white", linewidth = 0.2) +  # 堆叠条形图,白色边框
  geom_text(
    aes(label = 人数),
    position = position_stack(vjust = 0.5),  # 标签居中显示
    size = 3.5,
    color = "black"
  ) +
  scale_fill_manual(values = c("未生还" = "#F8766D", "生还" = "#00BFC4")) +  # 自定义颜色
  labs(
    title = "泰坦尼克号各舱位生还情况",
    x = "舱位等级",
    y = "人数",
    fill = "生还情况"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5),  # 标题居中
    legend.position = "top"                  # 图例放在顶部
  )

4.3 利用ggiraphExtra包ggSpine()

library(DT)
# 数据处理
df<-data %>% 
  select(Class,Survived,Freq) %>%
  summarise(n=sum(Freq),.by=c(Class,Survived)) %>%
  mutate(percent=n*100/sum(n),.by="Survived")
datatable(df)
ggSpine(data=df,aes(x=Survived,y=percent,fill=Class),stat="identity",
  palette="Reds",labelsize=3,reverse=TRUE)  # 反转调色板颜色

4.4 介绍图形特点和信息

  • 直观展示生还和未生还的人的舱位比例,显现舱位等级对生还率的影响

5 树状图和旭日图

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

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

data = as.data.frame(Titanic)
DT::datatable(data,rownames = FALSE)
# 图(a)分层顺序:Sex—Class—Age-Survived
treemap(data,index=c("Sex","Class","Age","Survived"),  # 设置聚合索引的列名称
  vSize="Freq",                                  # 指定矩形大小的列名称
   fontsize.labels=9,                             # 设置标签字体大小
  position.legend="bottom",                      # 设置图例位置
  title="(a) 分层顺序:Sex—Class—Age-Survived")

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

  • 通过d3r::d3_nest将数据框转化为层次数据“d3.js”作为绘图输入
library(d3r)
df<-data%>%select(Sex,Class,Age,Survived,Freq)  # 根据需要调整列变量的位置
df_tree<-d3_nest(df,value_cols="Freq")             # 将数据框转换为“d3.js”层次结构
datatable(df,rownames = FALSE)
library(sunburstR)
sunburst(data=df_tree,           # 绘制旭日图
   valueField="Freq",    # 计算大小字段的字符为vSize
   count=TRUE,                   # 在解释中包括计数和总数
   sumNodes=TRUE)                # 默认总和节点=TRUE
Legend

5.3 介绍图形特点和信息

6 热图和南丁格尔玫瑰图

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

6.1 数据准备

library(dplyr)
library(DT)

df <- as.data.frame(Titanic) %>%
  select(Class, Survived, Freq) %>%
  group_by(Class, Survived) %>%
  summarise(人数 = sum(Freq), .groups = "drop") %>%
  rename(乘客舱位 = Class, 生还情况 = Survived)

datatable(df, rownames = FALSE)

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

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

library(ggiraphExtra)
library(ggplot2)

p1 <- ggHeatmap(df, 
               aes(x = 乘客舱位, y = 生还情况, fill = 人数),
               color = "white") +
  scale_fill_gradient(low = "white", high = "red") +
  ggtitle("泰坦尼克号生还情况矩形热图") +
  theme_minimal()

p2 <- ggHeatmap(df,
               aes(x = 乘客舱位, y = 生还情况, fill = 人数),
               polar = TRUE) +
  scale_fill_gradient(low = "white", high = "blue") +
  ggtitle("泰坦尼克号生还情况极坐标热图") +
  theme_minimal()

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

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

# 计算标签位置 ypos
df <- df %>%
  group_by(乘客舱位) %>%
  arrange(生还情况) %>%  # 确保堆叠顺序(No 在下,Yes 在上)
  mutate(cumsum = cumsum(人数),  # 累计人数
         ypos = cumsum - (人数 / 2)) %>%  # 标签位置在每个堆叠段的中间
  ungroup()

# 检查添加了 ypos 的 df
print(df)
# A tibble: 8 × 5
  乘客舱位 生还情况  人数 cumsum  ypos
  <fct>    <fct>    <dbl>  <dbl> <dbl>
1 1st      No         122    122  61  
2 2nd      No         167    167  83.5
3 3rd      No         528    528 264  
4 Crew     No         673    673 336. 
5 1st      Yes        203    325 224. 
6 2nd      Yes        118    285 226  
7 3rd      Yes        178    706 617  
8 Crew     Yes        212    885 779  
# 绘制玫瑰图
# 自定义颜色(为 No 和 Yes 设置两种红色)
palette <- c("No" = "#FF9999", "Yes" = "#FF3333")

# 计算角度(基于 Class 数量)
n_groups <- length(unique(df$乘客舱位))  # 4 个 Class
myangle <- seq(0, 360, length.out = n_groups + 1)[1:n_groups]

# 绘制玫瑰图
p <- ggplot(df, aes(x = 乘客舱位, y = 人数, fill = 生还情况)) + 
  geom_col(width = 1, color = "grey20", position = "stack") +  # 堆叠条形图
  geom_text(aes(y = ypos, label = 人数),  
            size = 3.5, 
            color = "black", 
            show.legend = FALSE) +
  coord_polar(theta = "x", start = 0) +    # 极坐标转换
  scale_fill_manual(values = palette) +    # 手动指定填充颜色
  theme_minimal() +
  theme(axis.text.x = element_text(size = 10, angle = myangle),
        legend.position = "right") +
  labs(y = "人数", title = "乘客生存情况玫瑰图")

# 显示图形
print(p)

6.4 介绍图形特点和信息

  • 直观展示不同舱位等级的生还比例,反应不同舱位对生还率的影响以及生存情况的人数分布

7 饼环图

绘制Class和 Sex的饼环图。

7.1 数据准备

# 加载必要的包
library(dplyr)
library(ggiraphExtra)
library(gridExtra)
library(DT)

# 加载 Titanic 数据
data <- as.data.frame(Titanic)

# 按 Class 和 Sex 分组汇总人数,并排序
df <- data %>%
  group_by(Class, Sex) %>%
  summarise(人数 = sum(Freq), .groups = "drop") %>%
  mutate(Class = factor(Class, levels = c("1st", "2nd", "3rd", "Crew")),
         Sex = factor(Sex, levels = c("Male", "Female"))) %>%
  arrange(Class, Sex)  # 确保 Class 和 Sex 按顺序排列

# 为 p2 准备按 Sex 和 Class 排序的数据
df_alt <- df %>%
  arrange(Sex, Class)



datatable(df,rownames = FALSE)

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

p1<-ggPieDonut(
  data = df,
  aes(pies = Class, donuts = Sex, count = 人数),
  title = "舱位分布(饼图)与性别分布(环图)",
  interactive = FALSE,
  labelposition = 1
)
p2<-ggPieDonut(
  data = df,
  aes(pies = Sex, donuts = Class, count = 人数),
  title = "性别分布(饼图)与舱位分布(环图)",
  interactive = FALSE,
  labelposition = 1
)
grid.arrange(p1,p2,ncol = 2)

7.3 介绍图形特点和信息

  • 展示不同舱位等级和性别的比例关系