第三章 类别数据可视化

Author

221527106曾乐

1 解释原始数据

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

    Titanic 是 R 内置数据集(来自 datasets 包),原始数据以 多维数组(table) 形式存储,使用 as.data.frame() 可转换为数据框。转换后包含以下变量:

    1. 变量列表及类型

    Class(分类变量,乘客舱位等级)

    Sex(分类变量,乘客性别)

    Age(分类变量,乘客年龄组)

    Survived(分类变量,是否幸存)

    Freq(数值变量,对应组合的乘客数量)

    2. 分类变量的具体类别

    Class,Sex,Age,Survived

data = as.data.frame(Titanic)
DT::datatable(data,rownames = FALSE)

2 条形图

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

2.1 数据准备

  • 下面代码作了什么数据处理?为什么要这样处理?

    这段代码对泰坦尼克号数据集 (Titanic) 进行了 数据汇总和重命名,最终生成一个交互式表格展示不同性别 (Sex) 和生还状态 (Survived) 的乘客人数。

    数据聚合:原始 Titanic 数据是 长格式,每组 (Sex, Survived) 组合对应多行(如不同舱位、年龄),sum(Freq) 可汇总出 不同性别和生还状态的总人数。

    中文化列名:方便中文用户理解(如将 Sex 改为 性别)。

    交互式展示:DT::datatable() 比静态表格更灵活,适合在 R Markdown 或 Shiny 中展示。

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

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

2.3 介绍图形特点和信息

  • 垂直并列条形图

    1. 图形特点

      • 采用 并列条形 展示不同性别(男/女)的生还(是/否)人数分布。

      • 横轴为性别(男、女),每组性别包含两个并列条形,分别代表“生还”和“未生还”。

      • 纵轴为人数,数值标签直接标注在条形上方。

    2. 传达信息

      • 男性:未生还人数显著高于生还人数(1364 vs 367)。

      • 女性:生还人数高于未生还人数(344 vs 126),体现“妇孺优先”的逃生原则。

      • 对比:女性生还率(约73%)远高于男性(约21%)。

    3. 适用场景

      • 适合比较同一性别内不同生还状态的人数差异。
  • 垂直堆叠条形图

    1. 图形特点

      • 采用 堆叠条形 展示性别与生还状态的组合分布。

      • 每个性别对应一个总高度条形,按生还状态(是/否)分段堆叠。

      • 颜色区分生还状态,图例标注颜色含义。

    2. 传达信息

      • 男性:未生还部分(深色)占主导,生还部分(浅色)较小。

      • 女性:生还部分(浅色)占比更大,与并列条形图结论一致。

      • 总数对比:男性总人数(1364+367=1731)多于女性(126+344=470)。

    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")+# 绘制条形图
  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.5,y=800,label="百分比(%)",angle=90,size=3.5)+
   annotate("text",x=4,y=800,label="累积百分比曲线",size=3.5)   # 添加注释文本

3.3 介绍图形特点和信息

3.3.1 图形特点

  • 双纵坐标:左侧纵坐标表示人数(单位:人),范围从 0 到 750 ;右侧纵坐标表示百分比(%),范围从 0% 到 100% 。这种设计能同时展示具体数量和比例关系。

  • 柱状图:不同颜色的柱子代表各乘客舱位的人数。柱子颜色从深红到浅红过渡,视觉上有层次感。其中 Crew 对应的柱子最高,人数为 885 人;3rd 对应的人数为 706 人;1st 对应的人数为 325 人;2nd 对应的人数为 285 人 。

  • 折线图:黑色折线代表累积百分比曲线,折线上的菱形标记点标注了关键的百分比数值,如 Crew 对应的 40.2% 、3rd 对应的 72.3% 、1st 对应的 87.1% 以及终点的 100% ,展示了随着舱位类别变化,人数的累积占比情况。

3.3.2 传达信息

  • 人数分布:可以直观地看出 Crew 的人数最多,其次是 3rd 乘客,1st 和 2nd 乘客人数相对较少。这反映了不同舱位在总人数中的占比情况。

  • 累积占比:累积百分比曲线展示了各舱位人数在总体中所占的累积比例。例如,Crew 和 3rd 舱位的人数累积占比达到了 72.3%,说明这两个部分占据了总人数的大部分;加上 1st 舱位后,累积占比达到 87.1% ,表明这三个部分涵盖了绝大部分人数。

4 脊形图

绘制Class和 Survived 的脊形图。

4.1 数据准备

df<- data |> select(Class,Survived,Freq) |> 
  summarise(Freq=sum(Freq),.by=c("Class","Survived"))|>
  mutate(percent=Freq*100/sum(Freq),.by="Class")

datatable(df,rownames = FALSE)

4.2 利用geom_col() 作图

p1 = ggplot(df)+aes(x=Class,y=percent,fill=Survived)+ylab("百分比(%)")+
  geom_bar(stat="identity",width=0.8,color="grey50")+
  scale_fill_brewer(palette="Blues")
p2 = ggplot(df)+aes(x=Survived,y=percent,fill=Class)+ylab("百分比(%)")+
  geom_bar(stat="identity",width=0.8,color="grey50")+
  scale_fill_brewer(palette="Blues")
grid.arrange(p1,p2,ncol=1) 

4.3 利用ggiraphExtra包ggSpine()

df1 <- df %>% mutate(Class=factor(Class,levels = c("Crew","3rd","2nd","1st")))
ggSpine(data = df1,aes(x=Survived,fill=Class,y=percent),stat = "identity",
  palette="Blues",labelsize=3,reverse=TRUE)

4.4 介绍图形特点和信息

4.4.1 图形特点

  • 堆积柱状结构:有两根柱子,分别对应 “Survived” 中的 “No”(未存活)和 “Yes”(存活)两种情况 。每根柱子按类别(Crew、3rd、2nd、1st )进行堆积,直观呈现各部分占比。

  • 颜色区分与占比标注:不同类别用不同深浅的蓝色系区分,并且每个部分都标注了具体的百分比数值,便于准确读取数据。

  • 双维度展示:横轴表示是否存活的类别,纵轴表示不同的乘客舱位等级,能同时从两个维度观察数据分布。

4.4.2 传达信息

  • 未存活情况(No ):Crew 占比 30.8%,3rd 占比 30.3%,2nd 占比 23.7%,1st 占比 15.2% 。可以看出 Crew 和 3rd 在未存活人群中占比较大。

  • 存活情况(Yes ):1st 占比 40.8%,2nd 占比 27.1%,3rd 占比 16.5%,Crew 占比 15.7% 。表明 1st 和 2nd 在存活人群中占比较高。

  • 舱位与存活关系:对比两根柱子可发现,1st 和 2nd 舱位存活比例相对较高,而 Crew 和 3rd 舱位未存活比例相对较高,反映出舱位等级可能与存活概率存在关联。

5 树状图和旭日图

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

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

df <- data 
# 图(a)分层顺序:
treemap(df,index=c("Class","Sex","Age","Survived"),  # 设置聚合索引的列名称
  vSize="Freq", 
  # 指定矩形大小的列名称
  fontsize.labels=7,                             # 设置标签字体大小
  position.legend="bottom",                      # 设置图例位置
  title="(a) 分层顺序:乘客船舱—性别—年龄—生还")

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

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

5.3 介绍图形特点和信息

5.3.1 图形特点

  • 结构设计:采用环形分层结构,由多个同心圆环组成,每个圆环被分割成不同颜色和大小的扇形区域,形成类似旭日光芒的视觉效果,层级关系通过圆环的嵌套体现 。

  • 色彩运用:使用多种颜色区分不同的数据类别或层级,色彩丰富且搭配协调,便于在视觉上区分各个部分。

  • 简洁性:背景为纯白色,没有多余的装饰元素或网格线,仅在右上角有一个 “Legend” 标识用于指示图例位置(但未展示具体图例内容 ),整体风格简洁明了,突出数据展示。

5.3.2 传达信息

  • 比例关系:通过扇形区域的大小直观展示各部分在对应层级以及整体中所占的比例。面积较大的扇形区域代表其对应类别在该层级或整体中占比较高,反之则占比较低 。

  • 层级关系:同心圆环的嵌套结构暗示了数据的层级关系,从内到外可能代表从宏观到微观的分类,帮助观察者理解数据的层次结构。但由于缺少图例和具体标注,无法明确各颜色对应的具体类别、层级名称以及确切的比例数值。

6 热图和南丁格尔玫瑰图

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

6.1 数据准备

df<-data
datatable(df,rownames = FALSE)

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

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

p1<-ggHeatmap(data,aes(x=Class,y=Survived,fill=Freq),          # 绘制矩形热图
   addlabel=TRUE,                                      # 添加数值标签
   palette="Reds")+                                    # 使用红色调色板
   ggtitle("(a1) 矩形热图")                            # 添加标题
p2<-ggHeatmap(data,aes(x=Class,y=Survived,fill=Freq),polar=TRUE,
   addlabel=TRUE,palette="Reds")+                      # 绘制极坐标热图
   ggtitle("(a2) 极坐标热图")
grid.arrange(p1,p2,ncol=2)   

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

#这个数据需要根据class合并一下
df1 <- data%>%                                # 提取数据,构建新的数据框
  select(Class,Survived,Freq)%>%
  group_by(Class,Survived)%>%
  summarise(n=sum(Freq))%>%
  mutate(乘客船舱=fct_inorder(Class))    

df2 <- data%>%                                # 提取数据,构建新的数据框
  select(Class,Freq)%>%
  group_by(Class)%>%
  summarise(n=sum(Freq))%>%
  mutate(乘客船舱=fct_inorder(Class))    

df3 <- data%>%                                # 提取数据,构建新的数据框
  select(Survived,Freq)%>%
  group_by(Survived)%>%
  summarise(n=sum(Freq))

myangle<-seq(-20,-340,length.out=8)
# 设置标签角度,使之垂直于坐标轴
palette1<-brewer.pal(8,"Spectral")            # 设置离散型调色板

p1<-ggplot(df1,aes(x=interaction(Class,Survived),y=n,fill=interaction(Class,Survived)))+           
  geom_col(width=1,colour="grey20",fill=palette1)+# 绘制条形图
  coord_polar(theta="x",start=0)+   # 转化成极坐标图
  theme(axis.text.x=element_text(size=7,angle=myangle))+ # 设置坐标轴标签字体大小和角度
  ylab("人数")+                   # 设置y轴标签
  ggtitle("(a) 按原始顺序排序")

myangle<-seq(-20,-340,length.out=4)
# 设置标签角度,使之垂直于坐标轴
palette2<-brewer.pal(4,"Spectral")            # 设置离散型调色板
p2<-ggplot(df2,aes(x=Class,y=n,fill=Class))+           
  geom_col(width=1,colour="grey20",fill=palette2)+# 绘制条形图
  coord_polar(theta="x",start=0)+   # 转化成极坐标图
  theme(axis.text.x=element_text(size=7,angle=myangle))+ # 设置坐标轴标签字体大小和角度
  ylab("人数")+                   # 设置y轴标签
  ggtitle("(b) 按原始顺序排序")

myangle<-seq(-20,-340,length.out=2)
# 设置标签角度,使之垂直于坐标轴
p3<-ggplot(df3,aes(x=Survived,y=n,fill=Survived))+           
  geom_col(width=1,colour="grey20")+# 绘制条形图
  coord_polar(theta="x",start=0)+   # 转化成极坐标图
  theme(axis.text.x=element_text(size=7,angle=myangle))+ # 设置坐标轴标签字体大小和角度
  ylab("人数")+                   # 设置y轴标签
  ggtitle("(c) 按原始顺序排序")
gridExtra::grid.arrange(p1,p2,p3,ncol=2)      # 按2列组合图形

6.4 介绍图形特点和信息

  • 图形特点

    • 极坐标图形式:这组图形均采用极坐标形式展示数据,以圆心为中心,数据分布在圆周及半径方向上,角度和半径长度用于表示不同变量的数值大小。

    • 多图对比:包含三张图,分别从不同角度展示数据,且标题均标注 “按原始顺序排序” 。

    • 色彩区分:不同类别使用不同颜色区分,便于识别。图中还配有坐标轴标签(如 “人数” )和类别标签(如 “Crew”“1st”“Survived” 等 ),部分图有图例(如图 c )。

  • 传达信息

    • 图 (a) :展示的是 “interaction (Class, Survived)”,即舱位等级(Class )与是否存活(Survived )两个变量的交互情况。从图中可看到不同舱位等级下存活与未存活的人数分布,如 “Crew.Yes”“1st.No” 等组合,能直观比较各组合的人数差异。

    • 图 (b) :展示的是 “Class”,即仅从舱位等级角度,呈现不同舱位(Crew、1st、2nd、3rd )的人数分布情况,通过不同颜色扇形的大小可看出各舱位人数占比。

    • 图 (c) :展示的是 “Survived”,即仅从是否存活角度,呈现存活(Yes )和未存活(No )的人数分布,通过红色和青色区域大小对比,能明显看出未存活人数多于存活人数。

7 饼环图

绘制Class和 Sex的饼环图。

7.1 数据准备

df1 <- data%>%                                # 提取数据,构建新的数据框
  select(Class,Freq)%>%
  group_by(Class)%>%
  summarise(n=sum(Freq))

df2 <- data%>%                                # 提取数据,构建新的数据框
  select(Sex,Freq)%>%
  group_by(Sex)%>%
  summarise(n=sum(Freq))

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

library(ggiraphExtra)

p1<-ggDonut(df1,aes(donuts=Class,count=n),
  labelposition=1,labelsize=2.5,             # 设置标签位置和大小
  xmin=2,xmax=4,                             # 设置x的最小位置和最大位置
  title="(a) 乘客船舱")                          # 设置标题
p2<-ggDonut(df2,aes(donuts=Sex,count=n),
  labelposition=1,labelsize=2.5,xmin=2,xmax=4,
  title="(b) 性别")                          # 设置标题
grid.arrange(p1,p2,ncol=2)                   # 按2列组合图形p1和p3

7.3 介绍图形特点和信息

7.3.1 图形特点

  • 环形图形式:这两张图均为环形图,通过不同颜色的扇形区域展示各部分占比情况。环形图的中心为空白,各扇形围绕中心分布,视觉上较为直观。

  • 色彩区分:使用不同颜色区分不同类别,如在 “乘客船舱” 图中,不同颜色对应不同船舱等级;在 “性别” 图中,红色和浅蓝色分别对应男性和女性。

  • 百分比标注:每个扇形区域旁边都标注了相应的百分比数值,方便读者快速了解各部分在总体中所占的比例。

7.3.2 传达信息

  • 图 (a) - 乘客船舱:展示了不同船舱等级(Crew、1st、2nd、3rd )的占比情况。其中 Crew 占比最高,为 40.2%;其次是 3rd,占比 32.1%;1st 占比 14.8%;2nd 占比 12.9% 。可以看出 Crew 和 3rd 在总体中占比较大。

  • 图 (b) - 性别:展示了男性和女性的占比情况。男性占比 78.6%,女性占比 21.4% ,明显男性在总体中占比远高于女性。