如何在R语言双轴图中仅对第二个Y轴执行log10对数变换?
解决双轴图中仅对右Y轴(OD600)做log10变换并设置自定义刻度的问题
问题分析
你当前的代码错误地使用了scale_y_log10(),这个函数会直接修改左Y轴的刻度为对数格式,导致原本的线性荧光值轴被破坏。要仅对右Y轴(OD600)做log10变换,需要通过坐标映射转换实现:先将OD值的log10结果映射到左Y轴的线性范围,再通过sec_axis将映射值转换回原始OD的对数刻度。
修改后的代码
for (i in 1:length(unique(lf_combined$media)[grepl("^.+(gfp)$", unique(lf_combined$media))])) { print(i) # 定义OD的log10范围:0.01对应log10=-2,1对应log10=0 log_od_min <- log10(0.01) log_od_max <- log10(1) # 左Y轴范围:0到80000,计算映射系数 y_left_min <- 0 y_left_max <- 80000 coeff <- (y_left_max - y_left_min) / (log_od_max - log_od_min) p1 <- lf_combined_test[lf_combined_test$media %in% unique(lf_combined$media)[grepl("^.+(gfp)$", unique(lf_combined$media))][i], ] %>% filter(row_number() %% 3 == 1) %>% ggplot(aes(x = time)) + # 荧光值柱状图,直接用原始值 geom_bar(aes(y = normalized_gfp), stat = "identity", size = .1, fill = "green", color = "green", alpha = .4) + # OD值先取log10,再映射到左Y轴范围 geom_line(aes(y = (log10(od) - log_od_min) * coeff + y_left_min), size = 2, color = "tomato") + scale_x_continuous(breaks = round(seq(0, 92, by = 5), 1)) + geom_vline(xintercept = 12, linetype = "dotted", color = "blue", size = 1) + scale_y_continuous( limits = c(y_left_min, y_left_max), name = "Relative Flourescence [RFU]/[OD] ", # 右轴:将映射值转换回原始OD值,设置自定义刻度 sec.axis = sec_axis( ~10^((. - y_left_min)/coeff + log_od_min), name = "[OD600]", breaks = c(0.01, 0.1, 0.5, 1), labels = c("0.01", "0.1", "0.5", "1") ) ) + theme_grey() + theme( axis.title.y = element_text(color = "green", size = 13), axis.title.y.right = element_text(color = "tomato", size = 13) ) + ggtitle(paste("Relative fluorescence & OD600 time series for", unique(lf_combined$media)[grepl("^.+(gfp)$", unique(lf_combined$media))][i], sep = " ")) print(p1) }
关键修改点
- 映射逻辑调整:将OD值先做
log10()转换,再通过线性映射匹配左Y轴的0-80000范围,确保OD的对数变化能在左轴的线性空间中正确显示。 - 右轴转换函数:使用
~10^((. - y_left_min)/coeff + log_od_min)将左轴的映射值反向转换为原始OD值,实现对数刻度的显示。 - 自定义刻度设置:在
sec_axis中通过breaks和labels参数指定你需要的0.01、0.1、0.5、1刻度。 - 移除
scale_y_log10():避免破坏左Y轴的线性刻度。
内容的提问来源于stack exchange,提问作者Salt_Industry
相关产品推荐
相关产品推荐

