[数据分析与可视化] 数据绘图要点6-数据组过多

数据绘图要点6-数据组过多

比较几个数值变量的分布是数据展示中的一项常见任务。变量的分布可以使用直方图或密度图来表示,在同一轴上表示适量数据的组是非常有吸引力的。但是数据组过多将严重影响图表信息表现。

数据分布绘图实例

下面是一个示例,展示了人们如何感知词汇。短语“Highly likely”表示什么情况的概率问题。以下是人们给出概率分数分布结果。

# 加载库
library(tidyverse)
library(hrbrthemes)
library(viridis)
library(patchwork)

# 加载数据
data <- read.table("https://raw.githubusercontent.com/zonination/perceptions/master/probly.csv", header=TRUE, sep=",")
# 处理数据
data <- data %>% 
  gather(key="text", value="value") %>%
  mutate(text = gsub("\\.", " ",text)) %>%
  mutate(value = round(as.numeric(value),0))
head(data)
nrow(data)
A data.frame: 6 × 2
textvalue
<chr><dbl>
1Almost Certainly95
2Almost Certainly95
3Almost Certainly95
4Almost Certainly95
5Almost Certainly98
6Almost Certainly95

782

# 建立数据标注框
annot <- data.frame(
  text = c("Almost No Chance", "About Even", "Probable", "Almost Certainly"),
  x = c(5, 53, 65, 79),
  y = c(0.15, 0.4, 0.06, 0.1)
)
# 提取部分数据进行展示
data1 <-filter(data,text %in% c("Almost No Chance", "About Even", "Probable", "Almost Certainly")) 
data1 <-mutate(data1,text = fct_reorder(text, value))
head(data1)
nrow(data1)
A data.frame: 6 × 2
textvalue
<fct><dbl>
1Almost Certainly95
2Almost Certainly95
3Almost Certainly95
4Almost Certainly95
5Almost Certainly98
6Almost Certainly95

184

# 绘图
ggplot(data1, aes(x=value, color=text, fill=text)) +
geom_density(alpha=0.6) +
scale_fill_viridis(discrete=TRUE) +
scale_color_viridis(discrete=TRUE) +
geom_text( data=annot, aes(x=x, y=y, label=text, color=text), hjust=0, size=4.5) +
theme(
  legend.position="none",
  panel.spacing = unit(0.1, "lines"),
  strip.text.x = element_text(size = 8)
) +
xlab("") +
ylab("Assigned Probability (%)")

png

在这种情况下,图形非常整洁。人们给"Highly likely"表示"Almost No chance"这句话的概率在0%到20%之间,而表示"Almost Certainly"这句话的概率在 75%到100% 之间。但是当我们看看表示更多数据组会发生什么。

# Plot
data2<-mutate(data,text = fct_reorder(text, value)) 
ggplot(data2,aes(x=value, color=text, fill=text)) +
# 绘制密度图
geom_density(alpha=0.6) +
scale_fill_viridis(discrete=TRUE) +
scale_color_viridis(discrete=TRUE) +
theme(
  panel.spacing = unit(0.1, "lines"),
  strip.text.x = element_text(size = 8)
) +
xlab("") +
ylab("Assigned Probability (%)")

png

现在可以看到这个图过于杂乱了,无法区分组:在同一个图形上表示的数据组太多。如何避免这种情况?我们将在下一节介绍几种解决办法。

解决方法

箱形图

表示这种数据集的最常见方法是boxplot。它总结了每个组的主要特征,从而实现了高效的分布。请注意一些陷阱。对组进行排序以使图表更易于阅读通常是有意义的。如果组标签很长,请考虑使标签可读的水平版本。不过箱形图箱隐藏了样本大小的基本分布等信息,可以使用不显眼的点显示各个数据点。

ggplot(data2, aes(x=text, y=value, fill=text)) +
# 绘制箱形图
geom_boxplot() +
# 添加数据点
geom_jitter(color="grey", alpha=0.3, size=0.9) +
scale_fill_viridis(discrete=TRUE) +
theme(
  legend.position="none"
) +
# xy轴翻转
coord_flip() +
xlab("") +
ylab("Assigned Probability (%)")

png

小提琴图

只要样本量足够大,小提琴图通常是箱形图的良好替代品。它与箱形图非常接近,只是它通过定义更准确地描述了组分布。如果你有很多组,小提琴图可能不是最好的选择,因为小提琴图中每个数据组的展示结果往往都非常纤细,这使得很难想象其分布。在这种情况下,一个很好的替代方案是山脊图,这将在本文中进一步描述。

ggplot(data2,  aes(x=text, y=value, fill=text, color=text)) +
geom_violin(width=2.1, size=0.2) +
scale_fill_viridis(discrete=TRUE) +
scale_color_viridis(discrete=TRUE) +
theme(
  legend.position="none"
) +
coord_flip() +
xlab("") +
ylab("Assigned Probability (%)")
Warning message:
"position_dodge requires non-overlapping x intervals"

png

密度图

如果只有几组,可以在同一密度图上比较。这里只选择了四组来说明这个想法。如果有更多的组,图形就会变得杂乱无章,难以阅读。这个示例在前面也有提过,但是只能数据组少的情况合适。

# 绘图
ggplot(data1, aes(x=value, color=text, fill=text)) +
geom_density(alpha=0.6) +
scale_fill_viridis(discrete=TRUE) +
scale_color_viridis(discrete=TRUE) +
geom_text( data=annot, aes(x=x, y=y, label=text, color=text), hjust=0, size=4.5) +
theme(
  legend.position="none",
  panel.spacing = unit(0.1, "lines"),
  strip.text.x = element_text(size = 8)
) +
xlab("") +
ylab("Assigned Probability (%)")

png

但是,如果您有超过4个组,图形会变得过于混乱。如果想用密度图,用分组子图绘图的方式更加合适。这是分别研究每个组分布的好方法。但是,由于它们不共享相同的X轴,因此很难将组放在一起进行比较。一切都取决于您要回答的问题是什么。

ggplot(data2,aes(x=value, color=text, fill=text)) +
geom_density(alpha=0.6) +
scale_fill_viridis(discrete=TRUE) +
scale_color_viridis(discrete=TRUE) +
theme(
  legend.position="none",
  panel.spacing = unit(0.1, "lines"),
  strip.text.x = element_text(size = 8)
) +
xlab("") +
ylab("Assigned Probability (%)") +
# 分组绘图
facet_wrap(~text, scale="free_y")

png

直方图

直方图和密度图非常接近,表现处理方式也是类似,使用子图。但是直方图在这个例子的Y刻度对于每个组都是相同的,这与密度图上的先前示例不同。

ggplot(data2, aes(x=value, color=text, fill=text)) +
geom_histogram(alpha=0.6, binwidth = 5) +
scale_fill_viridis(discrete=TRUE) +
scale_color_viridis(discrete=TRUE) +
theme(
  legend.position="none",
  panel.spacing = unit(0.1, "lines"),
  strip.text.x = element_text(size = 8)
) +
xlab("") +
ylab("Assigned Probability (%)") +
facet_wrap(~text)

png

山脊图

在这个例子中,最好的选择可能是山脊图。它有小提琴图的所有优势,但避免了空间松散,因为组之间存在重叠。有效地描述了个体分布和组之间的比较。

# 加载专门的绘图库
library(ggridges)

ggplot(data2, aes(y=text, x=value,  fill=text)) +
geom_density_ridges(alpha=0.6, bandwidth=4) +
scale_fill_viridis(discrete=TRUE) +
scale_color_viridis(discrete=TRUE) +
theme(
  legend.position="none",
  panel.spacing = unit(0.1, "lines"),
  strip.text.x = element_text(size = 8)
) +
xlab("") +
ylab("Assigned Probability (%)")

png

参考

posted @ 2021-12-19 12:02  落痕的寒假  阅读(28)  评论(0编辑  收藏  举报