第三章 类别数据可视化

Author

221527125沈灿标

1 解释原始数据

  • Titanic数据集是datasets包的配套案例数据,可以通过as.data.frame将其转化为数据框。解析数据包含哪些变量,如果是分类变量分别有哪些类别?
  • 答:数值变量Freq,分类变量Class有1st 2nd 3rd Crew类别,分类变量Sex有Male Female类别,分类变量Age有Child Adult类别,分类变量Survived有Yes No类别。
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 介绍图形特点和信息

  • 直观上可以看出女性总人数中,生还者占比更高,男性总人数中,生还者占比较低;男性在总人数上比女性多。

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

palette<-rev(brewer.pal(4,"Reds"))        # 设置调色板
# 绘制条形图
p<-ggplot(df)+aes(x=乘客舱位,y=人数)+                
  geom_col(width=0.8,fill=palette,color="grey50")+# 绘制条形图
  scale_x_discrete(labels=c("Crew","1st","2nd","3rd"))+ # 将x轴的长标签折行
  geom_text(aes(x=乘客舱位,y=人数,label=人数,vjust=-0.5),size=3,color="gray50")+                      # 添加数值标签,垂直调整标签位置
   ylab("人数\n(人)")+               # 设置y轴标签 
  theme(axis.text.y=element_text(angle=90,hjust=0.5,vjust=0.5))+     # 调整y轴标签角度
  theme(legend.position="none")         # 删除图例

# 绘制折线和点
p1<-p+geom_line(aes(x=as.numeric(乘客舱位),y=累积百分比*max(人数/100)))+     # 绘制累积百分比曲线
  geom_point(aes(x=as.numeric(乘客舱位),y=累积百分比*max(人数/100)),
             size=2.5,shape=23,fill="white")+                     # 绘制点
  geom_text(aes(label=累积百分比,x=乘客舱位,y=1*累积百分比*max(人数/100),
    hjust=0.6,vjust=-0.95),size=3,colour="blue3")+                # 添加百分比数值标签
  scale_y_continuous(sec.axis = sec_axis(~./max(df$人数/100)))# 添加坐标轴
p1+annotate("text",x=4.3,y=800,label="百分比(%)",angle=90,size=3.5)+
   annotate("text",x=3,y=700,label="累积百分比曲线",size=3.5)   # 添加注释文本

3.3 介绍图形特点和信息

  • 船员所占比例较大。二等舱与一等舱乘客数量差距较大

4 脊形图

绘制Class和 Survived 的脊形图。

4.1 数据准备

# 数据处理
df <- data %>%
  group_by(Class, Survived) %>%
  summarise(人数 = sum(Freq), .groups = "drop") %>%
  mutate(
    百分比 = 人数 * 100 / sum(人数),
    .by = "Class"  # 按舱位分组计算
  ) %>%
  rename(
    舱位等级 = Class,
    生存状态 = Survived
  )
datatable(df,rownames = FALSE)

4.2 利用geom_col() 作图

ggplot(df)+aes(x=生存状态,y=百分比,fill=舱位等级)+ylab("百分比(%)")+
  geom_bar(stat="identity",width=0.8,color="grey50")+
  scale_fill_brewer(palette="Blues")

4.3 利用ggiraphExtra包ggSpine()

ggSpine(data=df,aes(x=舱位等级,fill=生存状态,facet=生存状态),
  palette="Reds",labelsize=3,reverse=TRUE)  # 反转调色板颜色

4.4 介绍图形特点和信息

  • 在一等舱与二等舱的存活比例较大,船员及三等船舱的乘客未存活的比例较大。

5 树状图和旭日图

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

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

df <- as.data.frame(data) %>%
  group_by(Class, Sex, Age, Survived) %>%
  summarise(Freq = sum(Freq), .groups = "drop")

treemap(
  df,
  index = c("Class", "Sex", "Age", "Survived"),  # 层次变量
  vSize = "Freq",                                # 区块大小依据
  vColor = "Freq",                               # 颜色依据
  palette = "Reds",                              # 颜色方案
  title = "Titanic 乘客分布 (Class-Sex-Age-Survived)",
  fontsize.labels = c(12, 10, 8, 6)              # 调整每层标签字号
)

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

  • 通过d3r::d3_nest将数据框转化为层次数据“d3.js”作为绘图输入
library(d3r)
df<-data%>%select(Class,Sex,Age,Survived)  # 根据需要调整列变量的位置
df_tree<-d3_nest(df,value_cols="Survived")             # 将数据框转换为“d3.js”层次结构
datatable(df,rownames = FALSE)

5.3 介绍图形特点和信息

从年龄角度看乘客较大部分为成年人,且其中男性占比例较大为75.7%。身份为船员的成人男性在未存活中所占比重较大未30.4%。

6 热图和南丁格尔玫瑰图

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

6.1 数据准备

library(dplyr)
plot_data <- data %>%
  group_by(Class, Survived) %>%
  summarise(Freq = sum(Freq), .groups = "drop")
head(plot_data)
# A tibble: 6 × 3
  Class Survived  Freq
  <fct> <fct>    <dbl>
1 1st   No         122
2 1st   Yes        203
3 2nd   No         167
4 2nd   Yes        118
5 3rd   No         528
6 3rd   Yes        178

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

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

#
p1 <- ggHeatmap(
  data = plot_data,
  aes(x = Class, y = Survived, fill = Freq),  # Freq 作为颜色填充依据
  addlabel = TRUE,                            # 显示数值标签
  palette = "Reds",                           # 红色调色板
  color = "white"                             # 格子边框颜色
) +
  ggtitle("(a) 矩形热图:舱位等级与生存情况") +
  theme_minimal()

#
p2 <- ggHeatmap(
  data = plot_data,
  aes(x = Class, y = Survived, fill = Freq),
  polar = TRUE,                               # 启用极坐标
  addlabel = TRUE,
  palette = "Reds",
  color = "white"
) +
  ggtitle("(b) 极坐标热图:舱位等级与生存情况") +
  theme_minimal()

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

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

df <- as.data.frame(data) %>%
  select(Class, Survived, Freq) %>%
  filter(complete.cases(.)) %>%
  filter(Freq > 0) %>%
  group_by(Class, Survived) %>%
  summarise(Freq = sum(Freq), .groups = "drop") %>%
  as.data.frame()
p1 <- ggplot(df, aes(x = Class, y = Freq, fill = Class)) + 
  geom_col(width = 1, colour = "grey20") + 
  coord_polar(theta = "x", start = 0) +      # 转换为极坐标
  theme(
    axis.text.x = element_text(size = 10),   # 增大x轴标签字体
    legend.position = "right"                # 添加图例位置
  )
print(p1)

6.4 介绍图形特点和信息

  • 船员所占比例较大,船员及一等舱乘客的存活数量较高,存活人数最少的是二等舱的乘客。

7 饼环图

绘制Class和 Sex的饼环图。

7.1 数据准备

donut_data <- as.data.frame(Titanic) %>%
  group_by(Class, Sex) %>%
  summarise(Freq = sum(Freq), .groups = "drop") %>%
  as.data.frame()  # 确保转换为标准数据框

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

ggPieDonut(
  data = donut_data,
  aes(pies = Class, donuts = Sex, count = Freq),  # 关键映射
  interactive = TRUE,                             # 启用交互                      
  title = "泰坦尼克号乘客分布",                  # 主标题
)

7.3 介绍图形特点和信息

  • 内层乘客舱位数量最多的为船员,其次为三等舱;从外层观察可知,男性乘客比例显著高于女性;从内层与外层的交互来看,一等舱位女性的比例高于其他舱位。