[数据分析与可视化] 数据绘图要点11-雷达图的注意事项

数据绘图要点11-雷达图的注意事项

准确通过雷达图表现数据有许多值得需要思考的地方,本文主要介绍雷达图的一些注意事项。

雷达图绘制

基础雷达图

雷达图又称蜘蛛图或网络图,是一种二维图表类型,设计用于绘制多个定量变量的一个或多个数值系列。每个变量都有自己的轴,所有轴都连接在图形的中心。让我们考虑一个学生的考试成绩。他在数学、体育、统计学等十个主题上的得分范围为 0 到 20。雷达图为每个主题提供一个轴。通过该形状,您可以查看学生在哪些主题上表现出色或表现不佳。

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


# 创建数据
#设计随机种子
set.seed(42) 
# 设计数据
data <- as.data.frame(matrix( sample( 2:20 , 10 , replace=T) , ncol=10)) 
# 添加列名
colnames(data) <- c("math" , "english" , "biology" , "music" , "R-coding", "data-viz" , "french" , "physic", "statistic", "sport" )
# 在数据中添加每一列的最大范围和最小范围
data <- rbind(rep(20,10) , rep(0,10) , data)
data
A data.frame: 3 × 10
mathenglishbiologymusicR-codingdata-vizfrenchphysicstatisticsport
<dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl>
20202020202020202020
0 0 0 0 0 0 0 0 0 0
18 6 211 5191816 8 5

# 创建雷达图
par(mar=c(0,0,0,0))
radarchart( data, axistype=1, 
           # 自定义雷达图四边形
           # pcol设置四边形边框颜色,pfcol设置四边形填充颜色,plwd设置边框粗细
           pcol=rgb(0.9,0.6,0.5,0.9) , pfcol=rgb(0.2,0.5,0.5,0.5) , plwd=4, 
           # 自定义网格
           # cglcol设置网格线条颜色,cglty设置网格线条类型,axislabcol设置轴标签字体颜色
           # caxislabels设置轴的范围,cglwd设置网格线条粗细
           cglcol="black", cglty=2, axislabcol="blue", caxislabels=seq(0,20,5), cglwd=0.8,
           # vlcex设置类别标签位置大小
           vlcex=1.2 
)

png

多类别雷达图

在上一个图表中,只绘制了一个系列,显示了一名学生的表现。一个常见的任务是比较几个人。只需几个系列,就可以在同一图表上显示每个组。如下图所示,很明显,Shirley综合表现优于Sonia,除了在运动、英语和 R 编码方面。

# 创建数据
set.seed(1)
data <-as.data.frame(matrix( c( sample( 2:20 , 10 , replace=T), sample( 2:9 , 10 , replace=T)) , ncol=10, byrow=TRUE))
colnames(data) <- c("math" , "english" , "biology" , "music" , "R-coding", "data-viz" , "french" , "physic", "statistic", "sport" )
# 设置第二行第二列数据为19
data[2,2]=19
# 在数据中添加每一列的最大范围和最小范围
data <- rbind(rep(20,10) , rep(0,10) , data)
data
A data.frame: 4 × 10
mathenglishbiologymusicR-codingdata-vizfrenchphysicstatisticsport
<dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl>
20202020202020202020
0 0 0 0 0 0 0 0 0 0
5 8 2 312151920 211
719 3 8 2 8 6 6 2 2
# 设置颜色
colors_border=c( rgb(0.2,0.5,0.5,0.9), rgb(0.8,0.2,0.5,0.9)  )
colors_in=c( rgb(0.2,0.5,0.5,0.4), rgb(0.8,0.2,0.5,0.4)  )

# 创建雷达图
radarchart( data, axistype=1, 
           # 自定义四边形
           pcol=colors_border , pfcol=colors_in , plwd=4, plty=1 , 
           # 自定义网格
           cglcol="grey", cglty=1, axislabcol="grey", caxislabels=seq(0,20,5), cglwd=1.1,
           # 自定义标签
           vlcex=0.8 )

# 设置图例
# bty设置图例文字外边框样式,pch设置图例图标样式,col设置图例图标颜色
# text.col设置图例文字颜色,cex设置图例文字大小,pt.cex设置图例图标大小
legend(x=0.85, y=1, legend = c("Shirley", "Sonia"), bty = "n", pch=20 , col=colors_border , text.col = "black", cex=0.9, pt.cex=1.6)

png

对于两个或三个以上的系列,使用多子图是一个很好的做法,以避免出现杂乱的数字。每个学生都有自己的雷达图。很容易理解特定个体的特征,寻找形状的相似性可以让您找到具有相似特征的学生。

# 创建数据
set.seed(1)
data <-as.data.frame(matrix( sample( 2:20 , 60 , replace=T) , ncol=10, byrow=TRUE))
colnames(data) <- c("math" , "english" , "biology" , "music" , "R-coding", "data-viz" , "french" , "physic", "statistic", "sport" )
# 在数据中添加每一列的最大范围和最小范围
data <- rbind(rep(20,10) , rep(0,10) , data)
data
A data.frame: 8 × 10
mathenglishbiologymusicR-codingdata-vizfrenchphysicstatisticsport
<dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl>
20202020202020202020
0 0 0 0 0 0 0 0 0 0
5 8 2 312151920 211
1511 81016 61015 6 6
3111316 2 4 71111 7
1613 7 913 7 82011 7
15 3141915 7 22020 9
713 7 9 81218 514 9
# 设置颜色
colors_border=colormap(colormap=colormaps$viridis, nshades=6, alpha=1)
colors_in=colormap(colormap=colormaps$viridis, nshades=6, alpha=0.3)

# 设置标题
mytitle <- c("Max", "George", "Xue", "Tom", "Alice", "bob")

# 设置子图
par(mar=rep(0.8,4))
par(mfrow=c(2,3))

# 依次绘图
for(i in 1:6){
    radarchart( data[c(1,2,i+2),], axistype=1, 
    pcol=colors_border[i] , pfcol=colors_in[i] , plwd=4, plty=1 , 
    cglcol="grey", cglty=1, axislabcol="grey", caxislabels=seq(0,20,5), cglwd=0.8,
    vlcex=0.8,
    title=mytitle[i]
    )
}

png

雷达图存在的问题与解决方案

雷达图存在的问题

1 圆形布局表示更难阅读

沿着单个垂直或水平轴布局时,定量值更容易比较。这是对圆形布局的普遍指责。下图仅考虑一名学生的数据。比较条形图中的值更容易,也更准确。

# 创建数据
set.seed(1)
data <-as.data.frame(matrix( sample( 2:20 , 10 , replace=T) , ncol=10))
colnames(data) <- c("math" , "english" , "biology" , "music" , "R-coding", "data-viz" , "french" , "physic", "statistic", "sport" )

# 在数据中添加每一列的最大范围和最小范围
data <-rbind(rep(20,10) , rep(0,10) , data)
data
A data.frame: 3 × 10
mathenglishbiologymusicR-codingdata-vizfrenchphysicstatisticsport
<dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl>
20202020202020202020
0 0 0 0 0 0 0 0 0 0
5 8 2 312151920 211
# 创建雷达图
par(mar=c(0,0,0,0))
p1 <- radarchart( data, axistype=1, 
                 pcol=rgb(0.2,0.5,0.5,0.9) , pfcol=rgb(0.2,0.5,0.5,0.5) , plwd=4 , 
                 cglcol="grey", cglty=1, axislabcol="grey", caxislabels=seq(0,20,5), cglwd=0.8,vlcex=1.3 )

png


# 创建条形图
data %>% slice(3) %>% t() %>% as.data.frame() %>% add_rownames() %>% arrange(V1) %>% mutate(rowname=factor(rowname, rowname)) %>%
  ggplot( aes(x=rowname, y=V1)) +
    geom_segment( aes(x=rowname ,xend=rowname, y=0, yend=V1), color="grey") +
    geom_point(size=5, color="#69b3a2") +
    coord_flip() +
    theme(
      panel.grid.minor.y = element_blank(),
      panel.grid.major.y = element_blank(),
      axis.text = element_text( size=32),
      legend.position="none"
    ) +
    ylim(0,20) +
    ylab("mark") +
    xlab("")

png

2 不支持排名

在上面的例子中,棒棒糖图是有序的。它使您可以立即查看哪个主题的得分最高以及每个主题的排名。对于没有起点和终点的雷达图,这更加困难。

3 类别排序有巨大的影响

雷达图的读者可能会关注观察到的形状。这可能会产生误导,因为这种形状高度依赖于周围类别的顺序。查看使用相同数据制作的这些图表,以下三张图数据一样,但更改了类别排序。

# 创建数据
set.seed(7)
data <- as.data.frame(matrix( sample( 2:20 , 10 , replace=T) , ncol=10))
colnames(data) <- c("math" , "english" , "biology" , "music" , "R-coding", "data-viz" , "french" , "physic", "statistic", "sport" )
data[1,1:3]=rep(19,3)
data[1,6:8]=rep(4,3)
data <- rbind(rep(20,10) , rep(0,10) , data)
data
A data.frame: 3 × 10
mathenglishbiologymusicR-codingdata-vizfrenchphysicstatisticsport
<dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl>
20202020202020202020
0 0 0 0 0 0 0 0 0 0
191919 316 4 4 416 9
# 改变排序创建其他数据
data2 <- data[,sample(1:10,10, replace=FALSE)]
data2
data3 <- data[,sample(1:10,10, replace=FALSE)]
data3
A data.frame: 3 × 10
sportbiologymusicenglishdata-vizstatisticmathR-codingfrenchphysic
<dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl>
20202020202020202020
0 0 0 0 0 0 0 0 0 0
919 319 4161916 4 4
A data.frame: 3 × 10
frenchenglishmusicdata-vizbiologyphysicmathsportstatisticR-coding
<dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl>
20202020202020202020
0 0 0 0 0 0 0 0 0 0
419 3 419 419 91616
# 绘图
par(mar=c(0,0,0,0))
par(mfrow=c(3,1))
radarchart( data, axistype=1, pcol=rgb(0.2,0.5,0.5,0.9) , pfcol=rgb(0.2,0.5,0.5,0.5) , plwd=4 ,   
           cglcol="grey", cglty=1, axislabcol="grey", caxislabels=seq(0,20,5), cglwd=0.8, vlcex=0.8  )
radarchart( data2, axistype=1, pcol=rgb(0.2,0.5,0.5,0.9) , pfcol=rgb(0.2,0.5,0.5,0.5) , plwd=4 ,  
           cglcol="grey", cglty=1, axislabcol="grey", caxislabels=seq(0,20,5), cglwd=0.8, vlcex=0.8  )
radarchart( data3, axistype=1, pcol=rgb(0.2,0.5,0.5,0.9) , pfcol=rgb(0.2,0.5,0.5,0.5) , plwd=4 ,   
           cglcol="grey", cglty=1, axislabcol="grey", caxislabels=seq(0,20,5), cglwd=0.8, vlcex=0.8  )

png

4 不确定的数值比例

雷达图显示几个定量变量的值,所有变量都表示在一个轴上。在前面的示例中,所有变量(范围从0 到 20的)共享相同的比例和相同的单位。但雷达图也可以显示完全不同的变量。在这种情况下,不要忘记为每个显示一个明显的比例:否则读者会期望相同的比例。

5 对差异的过度评估

雷达图中形状的面积也呈二次而非线性增加,这可能会导致观看者认为微小的变化比实际情况更重要。在下面的示例中,左边的学生在每个主题上的得分为 7,而右边的学生在每个主题上的得分为 14。但是,右图的面积是左图面积的两倍多。

# 创建数据
data <- as.data.frame(matrix( c(7,7,7,7,7) , ncol=5))
colnames(data) <- c("math" , "english" , "biology" , "music" , "R-coding")
data <- rbind(rep(20,10) , rep(0,10) , data)
data
data2 <- data
data2[3,] <- rep(14,5)
data2
A data.frame: 3 × 5
mathenglishbiologymusicR-coding
<dbl><dbl><dbl><dbl><dbl>
2020202020
0 0 0 0 0
7 7 7 7 7
A data.frame: 3 × 5
mathenglishbiologymusicR-coding
<dbl><dbl><dbl><dbl><dbl>
2020202020
0 0 0 0 0
1414141414
# 绘图
par(mar=rep(0,4))
par(mfrow=c(2,1))
radarchart( data, axistype=1, pcol=rgb(0.2,0.5,0.5,0.9) , pfcol=rgb(0.2,0.5,0.5,0.5) , 
           plwd=4 , cglcol="grey", cglty=1, axislabcol="grey", caxislabels=seq(0,20,5), cglwd=0.8, vlcex=0.8  )
radarchart( data2, axistype=1, pcol=rgb(0.2,0.5,0.5,0.9) , pfcol=rgb(0.2,0.5,0.5,0.5) , 
           plwd=4 , cglcol="grey", cglty=1, axislabcol="grey", caxislabels=seq(0,20,5), cglwd=0.8, vlcex=0.8  )

png

解决方案

如果您要显示单个系列并且所有定量变量都具有相同的比例,则使用条形图或棒棒糖图,对变量进行排名:

# 创建数据
set.seed(1)
data <-as.data.frame(matrix( sample( 2:20 , 10 , replace=T) , ncol=10))
colnames(data) <- c("math" , "english" , "biology" , "music" , "R-coding", "data-viz" , "french" , "physic", "statistic", "sport" )
data <-rbind(rep(20,10) , rep(0,10) , data)

# 绘制条形图
data %>% slice(3) %>% t() %>% as.data.frame() %>% add_rownames() %>% arrange(V1) %>% mutate(rowname=factor(rowname, rowname)) %>%
  ggplot( aes(x=rowname, y=V1)) +
    geom_segment( aes(x=rowname ,xend=rowname, y=0, yend=V1), color="grey") +
    geom_point(size=5, color="#69b3a2") +
    coord_flip() +
    theme(
      panel.grid.minor.y = element_blank(),
      panel.grid.major.y = element_blank(),
      axis.text = element_text( size=32 ),
      legend.position="none"
    ) +
    ylim(0,20) +
    ylab("mark") +
    xlab("")

png

如果您有两个系列要绘制,您仍然可以使用条形图和棒棒糖图。这是一个有2个系列的例子。它侧重于第一个学生(深色),并让您可以看到另一个学生(浅色)的表现如何。

# 创建数据
set.seed(1)
data <-as.data.frame(matrix( sample( 2:20 , 20 , replace=T) , ncol=10))
colnames(data) <- c("math" , "english" , "biology" , "music" , "R-coding", "data-viz" , "french" , "physic", "statistic", "sport" )
data <-rbind(rep(20,10) , rep(0,10) , data)

# 绘图
data %>% slice(c(3,4)) %>% t() %>% as.data.frame() %>% add_rownames() %>% arrange(V1) %>% mutate(rowname=factor(rowname, rowname)) %>%
  ggplot( aes(x=rowname, y=V1)) +
    # 绘制线条
    geom_segment( aes(x=rowname ,xend=rowname, y=V2, yend=V1), color="grey") +
    geom_point(size=5, color="#69b3a2") +
    # 设置透明度
    geom_point(aes(y=V2), size=5, color="#69b3a2", alpha=0.5) +
    coord_flip() +
    theme(
      panel.grid.minor.y = element_blank(),
      panel.grid.major.y = element_blank(),
      axis.text = element_text( size=32 )
    ) +
    ylim(0,20) +
    ylab("mark") +
    xlab("")

png

如果你有超过2个系列要绘制,使用条形图或棒棒糖图的分面也许可以解决问题:

# 创建数据
set.seed(1)
data <-as.data.frame(matrix( sample( 2:20 , 40 , replace=T) , ncol=10))
colnames(data) <- c("math" , "english" , "biology" , "music" , "R-coding", "data-viz" , "french" , "physic", "statistic", "sport" )
data <-rbind(rep(20,10) , rep(0,10) , data)
rownames(data) <- c("-", "--", "John", "Angli", "Baptiste", "Alfred")

# 绘图数据
data <- data %>% slice(c(3:6)) %>% 
  t() %>% 
  as.data.frame() %>% 
  add_rownames() %>% 
  arrange() %>% 
  mutate(rowname=factor(rowname, rowname)) %>% 
  gather(key=name, value=mark, -1)

# 编制数据
data$name <- recode(data$name, V1 = "John", V2 = "Angli", V3 = "Baptiste", V4 = "Alfred")

# 绘图
data %>% ggplot( aes(x=rowname, y=mark)) +
    geom_bar(stat="identity", fill="#69b3a2", width=0.6) +
    coord_flip() +
    theme(
      panel.grid.minor.y = element_blank(),
      panel.grid.major.y = element_blank(),
      axis.text = element_text( size=16 )
    ) +
    ylim(0,20) +
    ylab("mark") +
    xlab("") +
    facet_wrap(~name, ncol=4)

png

如果您有很多系列要绘制,或者您的变量没有相同的比例,那么最好的选择可能是切换到平行坐标图。

library(GGally)
# 导入iris数据
data <- iris

# 绘图
data %>% 
ggparcoord(
columns = 1:4, groupColumn = 5, order = "anyClass",
showPoints = TRUE, 
title = "Parallel Coordinate Plot for the Iris Data",
alphaLines = 0.3
) + 
scale_color_viridis(discrete=TRUE) 

png

参考

posted @ 2022-01-12 11:54  落痕的寒假  阅读(281)  评论(0编辑  收藏  举报