如何用R的ggtern绘制带绝对数值且间距均匀的三元图
问题描述
使用R语言的ggtern包绘制带有内部等高线的三元图,变量conc1、conc2、conc3与ZIP指标相关,要求三角形侧边显示绝对数值,但当前代码生成的刻度间距不均匀,希望实现类似示例图(均匀刻度+侧边绝对数值+内部等高线)的效果。
数据结构
tibble [125 × 14] (S3: tbl_df/tbl/data.frame) $ block_id : num [1:125] 1 1 1 1 1 1 1 1 1 1 ... $ conc1 : num [1:125] 0 0.3 0.15 0.075 0.0375 0 0.3 0.15 0.075 0.0375 ... $ conc2 : num [1:125] 0 0.05 0.05 0.05 0.05 0.05 0.025 0.025 0.025 0.025 ... $ conc3 : num [1:125] 0 0 0 0 0 0 0 0 0 0 ... $ ZIP_fit : num [1:125] 2.03 93.37 90.1 77.32 72.86 ... $ ZIP_ref : num [1:125] 2.03 89.87 69.93 52.5 43.38 ... $ ZIP_synergy : num [1:125] 0 3.5 20.2 24.8 29.5 ... $ HSA_ref : num [1:125] 2.03 85.48 51.92 38.55 40.02 ... $ HSA_synergy : num [1:125] 0 6.99 40.32 38.11 34.54 ... $ Loewe_ref : num [1:125] 2.03 84.81 53.22 35.13 20.92 ... $ Loewe_synergy: num [1:125] 0 7.66 39.02 41.53 53.64 ... $ Loewe_ci : num [1:125] NA 0.658 0.349 0.306 0.161 ... $ Bliss_ref : num [1:125] 2.03 91.22 70.65 56.03 46.33 ... $ Bliss_synergy: num [1:125] 0 1.26 21.59 20.64 28.23 ...
数据头部
# A tibble: 6 × 14 block_id conc1 conc2 conc3 ZIP_fit ZIP_ref ZIP_synergy HSA_ref HSA_synergy <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 1 1 0 0 0 2.03 2.03 0 2.03 0 2 1 0.3 0.05 0 93.4 89.9 3.50 85.5 6.99 3 1 0.15 0.05 0 90.1 69.9 20.2 51.9 40.3 4 1 0.075 0.05 0 77.3 52.5 24.8 38.6 38.1 5 1 0.0375 0.05 0 72.9 43.4 29.5 40.0 34.5 6 1 0 0.05 0 38.6 38.6 0 38.6 0 # ℹ 5 more variables: Loewe_ref <dbl>, Loewe_synergy <dbl>, Loewe_ci <dbl>, # Bliss_ref <dbl>, Bliss_synergy <dbl>
当前代码
library(ggtern) library(dplyr) library(readxl) conc1_values <- c(0, 0.3, 0.15, 0.075, 0.0375) conc2_values <- c(0, 0.05, 0.025, 0.0125, 0.00625) conc3_values <- c(0, 1, 0.5, 0.25, 0.125) eff_data <- read_xlsx("/Users/triple.xlsx") head(eff_data) str(eff_data) expanded_data <- expand.grid(conc1 = conc1_values, conc2 = conc2_values, conc3 = conc3_values) eff_data <- merge(expanded_data, eff_data, by = c("conc1", "conc2", "conc3")) ggtern(data = eff_data, mapping = aes(x = conc1, y = conc2, z = conc3)) + stat_density_tern(geom = 'polygon', n = 400, bdl = 0.01, aes(fill = ..level.., alpha = ..level..)) + geom_point(size = 2, color = "black") + scale_fill_gradient(low = "blue", high = "red", name = "", breaks = 1:5, labels = c("low", "", "", "", "high")) + scale_L_continuous(breaks = conc1_values, labels = round(conc1_values, 4)) + scale_R_continuous(breaks = conc2_values, labels = round(conc2_values, 4)) + scale_T_continuous(breaks = conc3_values, labels = round(conc3_values, 4)) + labs(title = "Density plot") + guides(fill = guide_colorbar(order = 2), alpha = guide_none()) + theme_rgbg() + theme_noarrows() + theme(legend.justification = c(0, 1), legend.position = c(0, 1))
解决方案
问题核心:ggtern默认按坐标比例生成刻度,而你的浓度值是等比序列,直接作为刻度断点会导致间距不均。需通过归一化坐标+自定义刻度标签实现均匀刻度+显示绝对数值的效果。
1. 归一化浓度数据
三元图要求x+y+z=1,先将原始浓度转换为比例坐标,同时保留原始值用于刻度标签:
eff_data <- eff_data %>% mutate(total_conc = conc1 + conc2 + conc3, x_norm = conc1 / total_conc, # 归一化到[0,1]的三元坐标 y_norm = conc2 / total_conc, z_norm = conc3 / total_conc)
2. 绘制带均匀刻度的三元图
使用归一化后的坐标绘图,设置等间距比例作为刻度断点,再将断点映射回原始绝对数值:
# 定义各轴最大浓度值 max_conc1 <- max(eff_data$conc1) max_conc2 <- max(eff_data$conc2) max_conc3 <- max(eff_data$conc3) # 生成均匀的比例刻度断点(0到1,步长0.25) scale_breaks <- seq(0, 1, by = 0.25) ggtern(data = eff_data, mapping = aes(x = x_norm, y = y_norm, z = z_norm)) + # 绘制ZIP协同效应的等高线(指定z为目标指标) stat_density_tern(geom = 'polygon', n = 400, bdl = 0.01, aes(fill = ..level.., alpha = ..level.., z = ZIP_synergy)) + geom_point(size = 2, color = "black") + # 自定义颜色渐变,关联ZIP指标 scale_fill_gradient(low = "blue", high = "red", name = "ZIP协同效应", breaks = seq(min(eff_data$ZIP_synergy), max(eff_data$ZIP_synergy), length.out = 5), labels = c("低", "", "", "", "高")) + # 设置各轴刻度:均匀比例断点,标签为对应绝对数值 scale_L_continuous(breaks = scale_breaks, labels = round(scale_breaks * max_conc1, 4)) + scale_R_continuous(breaks = scale_breaks, labels = round(scale_breaks * max_conc2, 4)) + scale_T_continuous(breaks = scale_breaks, labels = round(scale_breaks * max_conc3, 4)) + labs(title = "ZIP协同效应三元密度图", x = "conc1浓度", y = "conc2浓度", z = "conc3浓度") + guides(fill = guide_colorbar(order = 2), alpha = guide_none()) + theme_rgbg() + theme_noarrows() + theme(legend.justification = c(0, 1), legend.position = c(0, 1))
3. 关键注意事项
- 原代码中
stat_density_tern未指定z参数,默认计算坐标密度,需手动指定z = ZIP_synergy(或你关注的ZIP指标)才能生成关联指标的等高线 - 刻度均匀性由
scale_breaks的等间距比例保证,标签通过「比例×对应轴最大浓度」转换为原始绝对数值 - 若实验总浓度不固定,需根据实际需求调整归一化逻辑
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

