第三章 类别数据可视化

Author

221527213余语彤

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

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

# 图(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(
      "Male" = "男性",
      "Female" = "女性"
    )
  )+
  scale_fill_discrete("生还",
    labels = c(
      "Yes"= "是",
       "No" = "否"
    )
  )

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

2.3 介绍图形特点和信息

  • p1是堆叠条形图,p2是并列条形图。男性的死亡率较高,女性的生还率较高。

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=3.5,y=750,label="累积百分比曲线",size=3.5)   # 添加注释文本

3.3 介绍图形特点和信息

  • 直观地看到不同舱位的人数分布及其对总人数的贡献。船员人数最多,占据了总人数的40.2%,而三等舱人数也较多,累积百分比达到72.3%。头等舱和二等舱的人数相对较少,但累积百分比最终达到100%。

4 脊形图

绘制Class和 Survived 的脊形图(比例条形图)。

4.1 数据准备

df<-data |> 
  select(Class,Survived,Freq) |> 
  summarise(n=sum(Freq),.by=c(Survived,Class)) |> 
  rename(乘客舱位=Class,生还=Survived,人数=n ) |> 
  mutate(percent=人数*100/sum(人数),.by="乘客舱位") #计算累积百分比
         

datatable(df,rownames = FALSE)

4.2 利用geom_col() 作图

ggplot(df)+aes(x=乘客舱位,y=percent,fill=生还)+ylab("百分比(%)")+
  geom_col(stat="identity",width=0.8,color="grey50")+
  scale_fill_brewer(palette="Blues")

4.3 利用ggiraphExtra包ggSpine()

ggSpine(df,aes(x=生还,y=percent,fill=乘客舱位),stat = "identity",
  palette="Reds",labelsize=3,reverse=TRUE)  # 反转调色板颜色

4.4 介绍图形特点和信息

  • 主要展示不同舱位下生还和未生还的百分比分布,适合比较不同舱位的生存率。

5 树状图和旭日图

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

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

df<-data%>%
  as.data.frame()%>%
  rename(乘客舱位=Class,性别=Sex,年龄=Age,生还=Survived,频数=Freq) 

datatable(df,rownames = FALSE)
# 图(a)分层顺序:性别—年龄-生还—乘客舱位
treemap(df,index=c("性别","年龄","生还","乘客舱位"),  # 设置聚合索引的列名称
  vSize="频数",                                  # 指定矩形大小的列名称
  #fontsize.labels=5,                             # 设置标签字体大小
  position.legend="bottom",                      # 设置图例位置
  title="(a) 分层顺序:性别—年龄-生还—乘客舱位")

# 图(b)分层顺序:性别—年龄-生还—乘客舱位
treemap(df,index=c("性别","年龄","生还","乘客舱位"),  # 设置聚合索引的列名称
  vSize="频数",                                  # 设置指定矩形大小的列名称
  vColor="频数",                                 # 确定矩形颜色的列名称
  type="value",                                  # 设置矩形的着色方式
  #fontsize.labels=9,                             # 设置标签字体大小
  title="(b) 分层顺序:性别—年龄-生还—乘客舱位")

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

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

5.3 介绍图形特点和信息

  • 数据分层逻辑:从性别开始分(如男性/女性),再按年龄(成人/儿童),接着按生还(是/否),最后按舱位(1/2/3等舱)。这种分层方式可以直观展示不同群体的生还率和舱位分布。

  • 关键信息1.可以对比男性和女性的生还比例(例如女性生还率可能更高)。2.儿童(Child)可能生还率更高(“优先救助妇女儿童”的规则)。3.头等舱(1等舱)乘客的生还率可能显著高于其他舱位。4.矩形大小直接反映各组人数多少,例如成年男性三等舱乘客可能占比最大。

  • 图(a)仅通过矩形大小表示频数,颜色可能为固定色或随机色。图(b)通过颜色梯度强化了频数的可视化,使得高频数和低频数的对比更明显。

6 热图和南丁格尔玫瑰图

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

6.1 数据准备

df<-data%>%
  rename(乘客舱位=Class,性别=Sex,年龄=Age,生还=Survived,频数=Freq)

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

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

library(ggiraphExtra)
p1<-ggHeatmap(df,aes(x=乘客舱位,y=生还,fill=频数),
   addlabel=TRUE,palette="Blues")+                     # 使用蓝色调色板
   ggtitle("矩形热图")
p2<-ggHeatmap(df,aes(x=乘客舱位,y=生还,fill=频数),polar=TRUE,
   addlabel=TRUE,palette="Blues")+
   ggtitle("极坐标热图")

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

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

# 处理数据
df<-data%>%
  select(Class,Freq)%>%
  summarise(n=sum(Freq),.by=c(Class))%>%
  rename(乘客舱位=Class,人数=n)

f<-factor(df$乘客舱位,ordered=TRUE,levels=df$乘客舱位)
                                          # 将支出项目变为有序因子
df1<-data.frame(乘客舱位=f,人数=df$人数)

df2<-df1%>%
  mutate(乘客舱位=fct_inorder(乘客舱位))        

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

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

library(ggrepel)
p1<-p1+geom_text_repel(aes(y=人数,label=人数),size=2,color="grey30")# 为图形添加文本,并设置文本字体大小和颜色

# 图(b)按人数降序排序
# 处理数据
dfb <- data%>%
  select(Class,Freq)%>%
  summarise(n=sum(Freq),.by=c(Class))%>%
  rename(乘客舱位=Class,人数=n)%>%
  arrange(desc(人数)) %>% 
  mutate(乘客舱位=fct_inorder(乘客舱位))        

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

# 绘制玫瑰图
p2<-ggplot(dfb,aes(x=乘客舱位,y=人数,fill=乘客舱位))+           
  geom_col(width=1,colour="grey20")+# 绘制条形图
  coord_polar(theta="x",start=0)+   # 转化成极坐标图
  theme(axis.text.x=element_text(size=5,angle=myangle))+ # 设置坐标轴标签字体大小和角度
  ggtitle("(b) 按人数降序排序")+
  scale_fill_manual(values = palette)

p2<-p2+geom_text_repel(aes(y=人数-100,label=人数),size=2,color="grey30")# 为图形添加文本,并设置文本字体大小和颜色

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

##加入复合分组时图形更像玫瑰花
df <- data %>%
  group_by(Class, Survived) %>%
  summarise(n = sum(Freq)) %>%
  pivot_wider(names_from = Survived, values_from = n) %>%
  rename(乘客舱位=Class,存活 = Yes, 死亡 = No)%>%
  mutate(乘客舱位=fct_inorder(乘客舱位))
##玫瑰图需要长格式数据(一列表示分组,一列表示值)。使用 pivot_longer 将存活/死亡合并为一列
df_long <- df %>%
  pivot_longer(
    cols = c("存活", "死亡"),
    names_to = "生存",
    values_to = "人数"
  )

myangle<-seq(-20,-340,length.out=8)       # 设置标签角度,使之垂直于坐标轴

# 图(a)x轴为乘客舱位
p1<-ggRose(df_long,aes(x=乘客舱位,y=人数,fill=生存),
  stat="identity",palette="Reds",reverse=TRUE)+ylab("人数")+
  guides(fill=guide_legend(nrow=2,title=NULL))+  # 图例排成2行,去掉图例标题
  theme(legend.position="bottom")+
  theme(plot.title=element_text(size=10))+       # 设置标题字体大小
  theme(axis.text.x=element_text(size=8,color="red3",angle=myangle))+ # 设置坐标轴标签字体大小和角度
  ggtitle("(a)  x 轴为乘客舱位")

p2<-ggRose(df_long,aes(x=生存,y=人数,fill=乘客舱位),
  stat="identity",palette="Blues",reverse=FALSE)+ylab("人数")+
  guides(fill=guide_legend(nrow=2,title=NULL))+  # 图例排成2行,去掉图例标题
  theme(legend.position="bottom")+
  theme(plot.title=element_text(size=10))+       # 设置标题字体大小
  theme(axis.text.x=element_text(size=8,color="blue3"))+ # 设置坐标轴标签字体大小和角度
  ggtitle("(b)  x 轴为生存")

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

6.4 介绍图形特点和信息

  • 加入复合分组后的玫瑰图

    图 (a) 展示了不同舱位等级的乘客生存和死亡的分布情况,可以看出舱位等级对生存率的影响。

    图 (b) 展示了不同生存状态下,各舱位等级的乘客分布情况,可以看出生存率与舱位等级的关系。

7 饼环图

绘制Class和 Sex的饼环图。

7.1 数据准备

df<-data |> 
  select(Class,Sex,Freq) |> 
  summarise(n=sum(Freq),.by=c(Class,Sex)) |> 
  rename(乘客舱位=Class,性别=Sex,人数=n )

datatable(df,rownames = FALSE)

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

library(ggiraphExtra)

p<-ggPieDonut(df,aes(pies=性别,donuts=乘客舱位, count = 人数),
  title="性别为饼图,乘客舱位为环形图")

grid.arrange(p,ncol=1)

7.3 介绍图形特点和信息

  • 男性占比78.6%,女性占比21.4%;男性中头等舱乘客占比8.2%,二等舱乘客占比8.1%,三等舱乘客占比23.2%,船员占比39.2%。

  • 这个饼环图清晰地展示了泰坦尼克号乘客的舱位和性别分布情况。通过颜色和百分比标签,可以直观地看出不同舱位和性别的乘客比例。