如何在ggplot2中修改热力图标签文本的颜色
热力图中区分周末的可视化优化
问题背景
我在制作热力图时需要区分周末日期,目前的做法是将周末对应的值设为负数,通过颜色刻度让其呈现蓝色,但效果不理想。希望保留周末的正值,同时通过修改标签文本颜色或给热力图块添加边框等方式区分周末,已有布尔列weekend标记是否为周末,求更优的可视化方案。
原实现代码
hours <- c(16, 17, 0, 1, 2, 21, 22, 9, 19, 20) days <- c(0, 0, 3, 3, 3, 6, 6, 11, 21, 21) value <- c(3, 60, -18, -60, -23, 51, 48, 49, 47, 40) weekend<- c(FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) df <- data.frame(hours, days, value, weekend) h<-1 w<-1 ggplot(df, aes(days, hours)) + geom_tile(aes(fill = value, width = w, height = h)) + geom_text(aes(label = value), size = 3) + scale_fill_continuous(limits=c(-60,60),breaks=seq(-60,60,20),low = "blue", high = "red") + xlab("Day") + ylab("Hour") + scale_x_continuous( breaks = seq(0, 41, by = 7), expand = c(0.05, 0.05) ) + scale_y_continuous( breaks = seq(0, 23, by = 3), expand = c(0.05, 0.05) ) + coord_cartesian(xlim=c(0,41),ylim=c(0,23))
优化方案
方案1:根据周末设置标签文本颜色
保留所有数值的原始正值,直接利用weekend布尔列控制文本颜色,周末用白色文本,非周末用黑色,同时调整填充色刻度范围为0-60,让颜色仅反映数值大小:
hours <- c(16, 17, 0, 1, 2, 21, 22, 9, 19, 20) days <- c(0, 0, 3, 3, 3, 6, 6, 11, 21, 21) value <- c(3, 60, 18, 60, 23, 51, 48, 49, 47, 40) weekend<- c(FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) df <- data.frame(hours, days, value, weekend) h<-1 w<-1 ggplot(df, aes(days, hours)) + geom_tile(aes(fill = value, width = w, height = h)) + # 根据weekend列映射文本颜色 geom_text(aes(label = value, colour = weekend), size = 4) + # 自定义文本颜色规则 scale_colour_manual(values = c("black", "white")) + scale_fill_continuous(limits=c(0,60),breaks=seq(0,60,10),low = "white", high = "red") + xlab("Day") + ylab("Hour") + scale_x_continuous( breaks = seq(0, 41, by = 7), expand = c(0.05, 0.05) ) + scale_y_continuous( breaks = seq(0, 23, by = 3), expand = c(0.05, 0.05) ) + coord_cartesian(xlim=c(0,41),ylim=c(0,23))
方案2:给周末区块添加加粗边框
如果需要更直观的区分效果,可以给周末的热力块添加加粗边框,搭配文本颜色修改实现双重区分:
hours <- c(16, 17, 0, 1, 2, 21, 22, 9, 19, 20) days <- c(0, 0, 3, 3, 3, 6, 6, 11, 21, 21) value <- c(3, 60, 18, 60, 23, 51, 48, 49, 47, 40) weekend<- c(FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) df <- data.frame(hours, days, value, weekend) h<-1 w<-1 ggplot(df, aes(days, hours)) + # 根据weekend设置边框颜色和粗细 geom_tile(aes(fill = value, width = w, height = h, colour = weekend, size = weekend)) + geom_text(aes(label = value, colour = weekend), size = 4) + # 自定义边框和文本颜色规则 scale_colour_manual(values = c("black", "white")) + scale_size_manual(values = c(0.2, 1)) + # 非周末细边框,周末粗边框 scale_fill_continuous(limits=c(0,60),breaks=seq(0,60,10),low = "white", high = "red") + xlab("Day") + ylab("Hour") + scale_x_continuous( breaks = seq(0, 41, by = 7), expand = c(0.05, 0.05) ) + scale_y_continuous( breaks = seq(0, 23, by = 3), expand = c(0.05, 0.05) ) + coord_cartesian(xlim=c(0,41),ylim=c(0,23)) + theme(legend.position = "none") # 隐藏weekend相关图例
方案说明
- 方案1视觉干扰小,适合仅需轻度区分周末的场景;
- 方案2通过边框+文本颜色的双重标记,识别度更高,适合需要突出周末区块的场景;
- 两种方案均保留了数值的原始正值,避免了修改数值导致的可视化误导。
内容的提问来源于Stack Exchange,提问作者Stephen Clark
相关产品推荐
相关产品推荐

