如何用ggplot绘制带横竖分隔线的渐变色彩风险矩阵?
风险矩阵分隔线解决方案
问题说明
我正尝试使用ggplot绘制带有渐变色彩的风险矩阵,各颜色的边界由参考书籍定义,矩阵需严格遵循该标准。目前我已实现基于像素值的渐变配色方案,但无法添加所需的横向和纵向分隔线,希望设置如附图所示的分隔界限。请问是否可行?
用户现有代码
library(tidyverse) library(scales) library(dplyr) colour_breaks <- c(0,4,7,10,15) colours <- c("green","blue","yellow","orange","red") db <- seq(from=5,to=1,by=-0.1)%*%t(seq(from=1,to=5,by=0.1)) db<- as.data.frame(db) row.names(db) <- db[,1] colnames(db) <- seq(from=1,to=5,by=0.1) db$ID <- db[,1] db <- db[-nrow(db),] db_long <- db %>% gather(key = "variable", value = "value", -ID) %>% mutate(ID = as.numeric(ID)) %>% mutate(variable = as.numeric(variable)) plt1 <- ggplot(data=db_long, aes(x=as.numeric(variable), y=as.numeric(ID), fill=value)) + geom_raster() + coord_cartesian(clip = "off") + annotate('segment', x = 3.4, xend = 3.4, y = -Inf, yend = 1.4, size = 0.1, alpha = 0.4) + scale_x_continuous(expand = c(0, 0)) + scale_y_continuous(expand = c(0, 0), breaks=c(0,1,2,3,4,5)) + geom_hline(yintercept=1.4, alpha=0.4) + geom_hline(yintercept=2.4, alpha=0.4) + geom_hline(yintercept=3.5, alpha=0.4) + ylab("Condition") + xlab("Critic") + ggtitle("Risk Matrix") + scale_fill_gradientn( limits = range(db_long$value), colours = colours[c(1, seq_along(colours), length(colours))], values = c(0, scales::rescale(colour_breaks, from = range(db_long$value)), 1), ) + theme_bw() print(plt1)
解决方案
完全可行,只需通过geom_segment替代原有零散的分隔线绘制逻辑,就能精准匹配书籍要求的分段界限。修改后的代码如下:
library(tidyverse) library(scales) colour_breaks <- c(0,4,7,10,15) colours <- c("green","blue","yellow","orange","red") # 重构数据生成逻辑,避免原数据的冗余和异常 db <- seq(from=5,to=1.1,by=-0.1) %>% outer(seq(from=1,to=5,by=0.1), FUN = "*") %>% as.data.frame() colnames(db) <- seq(from=1,to=5,by=0.1) db$ID <- seq(from=5,to=1.1,by=-0.1) db_long <- db %>% gather(key = "variable", value = "value", -ID) %>% mutate(across(c(variable, ID), as.numeric)) # 用数据框统一管理所有分隔线的坐标,方便调整和维护 segments_df <- tibble( # 横向分段线 x_start = c(1, 1, 3.4), x_end = c(3.4, 5, 5), y_start = c(1.4, 2.4, 3.5), y_end = c(1.4, 2.4, 3.5), # 纵向分段线 x_start = c(x_start, 3.4), x_end = c(x_end, 3.4), y_start = c(y_start, 1.4), y_end = c(y_end, 5) ) plt1 <- ggplot(data=db_long, aes(x=variable, y=ID, fill=value)) + geom_raster() + coord_cartesian(clip = "off") + # 批量绘制所有自定义分隔线 geom_segment(data=segments_df, aes(x=x_start, xend=x_end, y=y_start, yend=y_end), size=0.1, alpha=0.4, inherit.aes=FALSE) + scale_x_continuous(expand = c(0, 0)) + scale_y_continuous(expand = c(0, 0), breaks=0:5) + labs(y="Condition", x="Critic", title="Risk Matrix") + scale_fill_gradientn( limits = range(db_long$value), colours = colours[c(1, seq_along(colours), length(colours))], values = c(0, scales::rescale(colour_breaks, from = range(db_long$value)), 1) ) + theme_bw() print(plt1)
关键修改说明
- 统一分隔线管理:用数据框定义所有分隔线的起点和终点,通过
geom_segment批量绘制,替代原有的零散geom_hline和annotate,更易调整以匹配书籍标准。 - 优化数据生成:重构矩阵数据的生成逻辑,避免原代码中ID列的重复值问题,数据处理更简洁。
- 简化代码结构:用
across批量转换数据类型,减少冗余代码。
内容的提问来源于stack exchange,提问作者Diogo Martins
相关产品推荐
相关产品推荐

