You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 20:04:56