data = as.data.frame(Titanic)
DT::datatable(data,rownames = FALSE)第三章 类别数据可视化
1 解释原始数据
Titanic数据集是datasets包的配套案例数据,可以通过as.data.frame将其转化为数据框。解析数据包含哪些变量,如果是分类变量分别有哪些类别?
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)
# 数据准备
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轴范围
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 介绍图形特点和信息
图一垂直并列条形图,清晰的呈现了在沉船事件里,男性生还,未生还,女性生还,未生还的具体数量。
图二垂直堆叠条形图,具有图一的优点,并且很直观地呈现 生还与未生还 在男性,女性中的比例关系。
从图中可知,该事件男性人数占比高,但生还比例远低于女性人数。
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 介绍图形特点和信息
该图是帕累托图,主坐标轴的图形形状是柱状图,从绝对数量上展现四个船舱的人数。其中,最左侧的柱子最高,是最主要的因素。副坐标轴是折线图,是从左到右,对四个因素的数量累积。
从图中可知:在乘客船舱中,人数最多的是船员(工作人员),共885人,占比为40.2,其次是三等舱,与船员人之和共占比72.3人,接着是一等舱,与船员,三等舱人员累积达到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)# 数据处理
df1<- data |> select(Class,Survived,Freq) |>
summarise(Freq=sum(Freq),.by=c("Class","Survived"))|>
mutate(percent=Freq*100/sum(Freq),.by="Survived")
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(df1)+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 介绍图形特点和信息
该图以一个分类变量X的不同取值为x轴,另一个分类变量Y在y轴,呈现变量Y在特定x值不同取值所占的比例,功能与堆叠条形图相似,但这个图形进行标准化,每个柱体高度相同,均为1.
这幅图可以看到在未生还的人员里,crew比例最高,其次是三等舱。而在生还人员里,一等舱,二等舱生还人数最多。
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”作为绘图输入
library(d3r)
df<-data%>%select(Class,Sex,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) # 默认总和节点=TRUE5.3 介绍图形特点和信息
树状图:具有层次结构,直观展示多级分类的组成和占比,面积比更易感知比例差异,适合高维分类数据。
观察图(a),第一个分层变量是乘客船舱,红色系是船员,人数最多,绿色系是三等舱,人数次于船员;一等舱,色系是棕黄色;二等舱色系是蓝色。第二个分类变量是性别,可以具体看不同船舱的性别比,男性居多。第三个分类变量是年龄,第四个分类变量为生还。
旭日图:从中心向外辐射。内环代表父类别,外环代表子类别。面积编码数值:每个扇区的角度或半径宽度由 (频数)决定,面积越大表示占比越高。具有交互功能,支持点击某一环段展开下一层级细节。
6 热图和南丁格尔玫瑰图
绘制Class和Survived 的点阵图、热图和南丁格尔玫瑰图。
6.1 数据准备
df<-data
datatable(df,rownames = FALSE)# 图(a)class和survived的点阵图
palette<-rev(brewer.pal(11,"Blues")) # 设置调色板
library(ggpubr)
p1<-ggballoonplot(df,x="Class",y="Survived", # 设置图形的x轴和y轴
shape=21, # 设置形状,默认21,可选22,23,24,25
size="Freq",fill="Freq", # 设置点的大小和填充颜色变量
size.range = c(1,12), # 设置最小点和最大点的范围
rotate.x.text=FALSE, # x轴文本标签不旋转
ggtheme=scale_fill_gradientn(colors=palette))+ # 设置渐变颜色
theme(axis.text.y=element_text(angle=90))+ # y轴标签旋转90度
ggtitle("(a) 乘客船舱和生还的点阵图")
# 图(b)按性别分面
p2<-ggballoonplot(df,x="Class",y="Survived",
size="Freq",fill="Freq",shape=22, # 用正方形表示数据点
size.range = c(1,12), # 设置最小点和最大点的范围
rotate.x.text=FALSE, # x轴文本标签不旋转
facet.by=c("Sex"), # 按性别分面
ggtheme=scale_fill_gradientn(colors=palette))+
theme(axis.text.y=element_text(angle=90))+
ggtitle("(b) 按性别分面的点阵图")
ggarrange(p1,p2,ncol=2) # 按2列组合图形p1和p26.2 利用ggiraphExtra::ggHeatmap()作热力图
分别作矩形热图和极坐标热图
library(ggiraphExtra)
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列组合图形# 创建降序排列的玫瑰图版本
# 处理df1 - 按Class和Survived分组
df1 <- data %>%
select(Class, Survived, Freq) %>%
group_by(Class, Survived) %>%
summarise(n = sum(Freq)) %>%
ungroup() %>%
mutate(interaction = interaction(Class, Survived),
interaction = fct_reorder(interaction, -n)) # 按人数降序排列
# 处理df2 - 按Class分组
df2 <- data %>%
select(Class, Freq) %>%
group_by(Class) %>%
summarise(n = sum(Freq)) %>%
ungroup() %>%
mutate(Class = fct_reorder(Class, -n)) # 按人数降序排列
# 处理df3 - 按Survived分组
df3 <- data %>%
select(Survived, Freq) %>%
group_by(Survived) %>%
summarise(n = sum(Freq)) %>%
ungroup() %>%
mutate(Survived = fct_reorder(Survived, -n)) # 按人数降序排列
# 设置角度和颜色
palette1 <- brewer.pal(8, "Spectral")
palette2 <- brewer.pal(4, "Spectral")
palette3 <- brewer.pal(2, "Spectral")
# 创建玫瑰图1 - Class和Survived交互
p1 <- ggplot(df1, aes(x = interaction, y = n, fill = interaction)) +
geom_col(width = 1, colour = "grey20") +
coord_polar(theta = "x", start = 0) +
scale_fill_manual(values = palette1) +
theme_minimal() +
theme(axis.text.x = element_text(size = 7, angle = seq(-20, -340, length.out = 8)),
legend.position = "none") +
ylab("人数") +
ggtitle("(a) 按船舱等级和生存状态分组(降序)")
# 创建玫瑰图2 - 仅Class
p2 <- ggplot(df2, aes(x = Class, y = n, fill = Class)) +
geom_col(width = 1, colour = "grey20") +
coord_polar(theta = "x", start = 0) +
scale_fill_manual(values = palette2) +
theme_minimal() +
theme(axis.text.x = element_text(size = 7, angle = seq(-20, -340, length.out = 4)),
legend.position = "none") +
ylab("人数") +
ggtitle("(b) 按船舱等级分组(降序)")
# 创建玫瑰图3 - 仅Survived
p3 <- ggplot(df3, aes(x = Survived, y = n, fill = Survived)) +
geom_col(width = 1, colour = "grey20") +
coord_polar(theta = "x", start = 0) +
scale_fill_manual(values = palette3) +
theme_minimal() +
theme(axis.text.x = element_text(size = 7, angle = seq(-20, -340, length.out = 2)),
legend.position = "none") +
ylab("人数") +
ggtitle("(c) 按生存状态分组(降序)")
# 组合图形
gridExtra::grid.arrange(p1, p2, p3, ncol = 2)6.4 介绍图形特点和信息
点图:2×2列联表,点的大小和颜色进行双重编码,维度可比热力图高。
点图(a), x坐标轴是乘客船舱,y坐标轴是生还。这里的颜色和大小均为人数,颜色越深,人数越多,圈越大,人数越多。
矩形热力图:2×2列联表,用颜色深浅表示矩阵数值大小。不同方块呈现均匀分布。
极坐标热力图:class沿圆周分段,survived沿径向分层,形成扇形区块。颜色和数值逻辑与矩形热图一致,但视觉呈现为极坐标。但是面积大小不代表数值大小
玫瑰图:极坐标下的堆叠条形图,扇区半径表示数值。视觉冲击力强,适合展示差异。
如图(a)按船舱等级和生存状态分组(降序),按人数降序开花,人数最多的是,未生还的船员,其次是未生还的三等舱乘客。
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和p37.3 介绍图形特点和信息
饼环图对一个变量不同取值进行切割,显示占比。不同扇形环的面积直观的展示占比
图一是对乘客船舱组织结构的直观展示,船员最多,其次是三等舱。
图二则是对性别变量的结构展示,可以观察到男性占比高达78.6%