ggplot2中geom_tile的动态缩放实现技术问询
问题需求
我有如下结构的数据框:
x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 proportion index cumulative_proportion 1 0 -1 0 0 0 -1 1 1 0 1 0 0 0.28423 1 0.28423 2 0 -1 0 0 0 -1 1 1 1 1 0 0 0.20511 2 0.48934 3 1 -1 0 0 0 -1 1 1 0 1 0 0 0.05751 3 0.54685 4 0 -1 0 0 1 -1 1 1 0 1 0 0 0.02388 4 0.57073 5 0 -1 0 0 0 -1 1 1 0 1 1 0 0.02217 5 0.59290 6 0 -1 0 0 0 -1 1 1 0 1 0 1 0.02098 6 0.61388
我想用geom_tile()做可视化,要求:
- 将变量x1至x12放在y轴
- x轴基于分类变量index,但要显示
cumulative_proportion的数值 - 瓷砖填充色由变量值-1、0、1决定
- 瓷砖按
proportion的大小进行宽度缩放
以下是未按比例缩放的基础代码:
plot.df <- reshape2::melt(plot.df, id.vars=c("index", "proportion", "cumulative_proportion")) ggplot(plot.df, aes(x=index, y=variable, fill=as.factor(value))) + geom_tile()
完整的数据框结构如下:
structure(list(x1 = c(0, 0, 1, 0, 0, 0, 1, 0, 0, 1), x2 = c(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1), x3 = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 1), x4 = c(0, 0, 0, 0, 0, 0, 0, 1, 1, 0), x5 = c(0, 0, 0, 1, 0, 0, 0, 0, 0, 0), x6 = c(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1), x7 = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1), x8 = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1), x9 = c(0, 1, 0, 0, 0, 0, 0, 0, 0, 0), x10 = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1), x11 = c(0, 0, 0, 0, 1, 0, 0, 0, 0, 0), x12 = c(0, 0, 0, 0, 0, 1, 1, 0, 1, 0), proportion = c(0.28423, 0.20511, 0.05751, 0.02388, 0.02217, 0.02098, 0.0165, 0.01383, 0.01185, 0.01013), index = 1:10, cumulative_proportion = c(0.28423, 0.48934, 0.54685, 0.57073, 0.5929, 0.61388, 0.63038, 0.64421, 0.65606, 0.66619)), row.names = c(NA, -10L), class = "data.frame")
解决方案
要实现瓷砖按proportion缩放,同时x轴显示cumulative_proportion,需要先计算每个瓷砖的左右边界位置,再映射到geom_tile()的参数中:
- 数据预处理:
library(tidyverse) library(reshape2) # 加载完整数据框 plot.df <- structure(list(x1 = c(0, 0, 1, 0, 0, 0, 1, 0, 0, 1), x2 = c(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1), x3 = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 1), x4 = c(0, 0, 0, 0, 0, 0, 0, 1, 1, 0), x5 = c(0, 0, 0, 1, 0, 0, 0, 0, 0, 0), x6 = c(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1), x7 = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1), x8 = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1), x9 = c(0, 1, 0, 0, 0, 0, 0, 0, 0, 0), x10 = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1), x11 = c(0, 0, 0, 0, 1, 0, 0, 0, 0, 0), x12 = c(0, 0, 0, 0, 0, 1, 1, 0, 1, 0), proportion = c(0.28423, 0.20511, 0.05751, 0.02388, 0.02217, 0.02098, 0.0165, 0.01383, 0.01185, 0.01013), index = 1:10, cumulative_proportion = c(0.28423, 0.48934, 0.54685, 0.57073, 0.5929, 0.61388, 0.63038, 0.64421, 0.65606, 0.66619)), row.names = c(NA, -10L), class = "data.frame") # 计算每个瓷砖的左右边界:x_start为前一组的累积比例(第一组为0),x_end为当前组的累积比例 plot.df <- plot.df %>% mutate(x_start = lag(cumulative_proportion, default = 0), x_end = cumulative_proportion) # 宽表转长表,保留边界信息 plot.df_long <- reshape2::melt(plot.df, id.vars=c("index", "proportion", "cumulative_proportion", "x_start", "x_end"))
- 绘制可视化图形:
ggplot(plot.df_long, aes(y = variable)) + # 用xmin/xmax定义瓷砖宽度,ymin/ymax确保瓷砖与y轴变量对齐 geom_tile(aes(xmin = x_start, xmax = x_end, ymin = as.numeric(variable)-0.5, ymax = as.numeric(variable)+0.5, fill = as.factor(value))) + # 设置x轴刻度为累积比例值,保留4位小数 scale_x_continuous(breaks = plot.df$cumulative_proportion, labels = round(plot.df$cumulative_proportion, 4)) + # 手动指定-1/0/1对应的填充色,提升可读性 scale_fill_manual(values = c("-1" = "darkblue", "0" = "white", "1" = "darkred"), name = "变量值") + # 设置标签和标题 labs(x = "累积比例", y = "变量", title = "按比例缩放的瓷砖图") + theme_bw()
核心说明:
- 通过
x_start和x_end的差值(即proportion)实现瓷砖宽度的按比例缩放 scale_x_continuous直接将x轴刻度替换为cumulative_proportion的数值,满足显示需求- 手动映射填充色让不同取值的瓷砖区分度更高
内容的提问来源于stack exchange,提问作者yrx1702
相关产品推荐
相关产品推荐

