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

使用ggplot2绘制对数转换值散点图并保留真实轴标签(解决报错)

解决ggplot2自定义轴转换报错的问题

问题背景

我有一个包含iso3(国家代码)、region(地区)、crude rate(粗率)、age-standardized rate(年龄标化率)的数据集,速率值可正、可负或为0。由于粗率和年龄标化率的数据存在偏斜,需要对其进行转换。想用ggplot2绘制转换后值的散点图,点按region变量着色,同时x、y轴保留原始数值的刻度标签。尝试的代码如下:

pdf("Graphs/Scatter_Crude_ASDR.pdf")
scatter <- ggplot(df_scatter, aes(x = crude, y = agestd, color = region, label=iso3)) +
  geom_point(size = 2) +
  scale_x_continuous(trans=sign(crude) * log(abs(crude) + 1)) +
  scale_y_continuous(trans=sign(agestd) * log(abs(agestd) + 1)) +
  geom_text(hjust=-0.2, vjust=0, size=3) +
  geom_abline() +
  geom_hline(yintercept = 0) +
  labs(
    x="Crude rate",y="Age-standardized rate") +
  theme(
    plot.title = element_text(color = "#0099f9", size = 20, face = "bold", hjust = 0.5),
    plot.subtitle = element_text(size = 13, face = "bold", hjust = 0.5),
    plot.caption = element_text(face = "italic", hjust = 0)
  ) +
  guides(colour = guide_legend(title = "region"))
print(scatter)
dev.off()

运行后报错:

Error in is.trans(x) : object 'crude' not found

数据集样例:

# A tibble: 10 × 4
   iso3  region     crude         agestd
   <chr> <chr>      <dbl>          <dbl>
 1 AFG   EMRO        67.5         198.  
 2 AGO   AFRO        18.3          72.9 
 3 ALB   EURO       255.          134.  
 4 AND   EURO        93.9          55.1 
 5 ARE   EMRO        21.4          55.7 
 6 ARG   AMRO       139.          101.  
 7 ARM   EURO       354.          251.  
 8 ATG   AMRO       -38.8         -32.9 
 9 AUS   WPRO        12.2           1.22
10 AUT   EURO        98.9          36.6 

问题原因

scale_x_continuous()的trans参数要求传入转换函数对象(比如内置的"log10",或是用scales::trans_new()自定义的转换规则),而直接在参数里写sign(crude) * log(abs(crude) + 1)时,R会把crude当成全局环境中的独立对象,而非数据框内的列,因此触发“找不到crude”的报错。

解决方案

使用scales包的trans_new()自定义带符号的对数转换,既能处理正负值和0,又能让ggplot自动将转换后的坐标映射回原始数值,保留轴的可读性。

完整代码

# 加载依赖包
library(ggplot2)
library(scales)

# 自定义带符号的对数转换:sign(x)*log(abs(x)+1)
signed_log_trans <- trans_new(
  name = "signed_log",
  # 正向转换:原始值→转换后的值
  transform = function(x) sign(x) * log(abs(x) + 1),
  # 反向转换:转换后的值→原始值(用于生成轴刻度)
  inverse = function(x) sign(x) * (exp(abs(x)) - 1),
  # 自定义刻度生成规则,适配正负值分布
  breaks = function(x) {
    c(seq(min(x[x<0]), 0, length.out = 5), seq(0, max(x[x>0]), length.out = 5))
  }
)

# 绘制散点图
pdf("Graphs/Scatter_Crude_ASDR.pdf")
scatter <- ggplot(df_scatter, aes(x = crude, y = agestd, color = region, label = iso3)) +
  geom_point(size = 2) +
  # 应用自定义转换
  scale_x_continuous(trans = signed_log_trans, name = "Crude rate") +
  scale_y_continuous(trans = signed_log_trans, name = "Age-standardized rate") +
  geom_text(hjust = -0.2, vjust = 0, size = 3) +
  geom_abline() +
  geom_hline(yintercept = 0) +
  theme(
    plot.title = element_text(color = "#0099f9", size = 20, face = "bold", hjust = 0.5),
    plot.subtitle = element_text(size = 13, face = "bold", hjust = 0.5),
    plot.caption = element_text(face = "italic", hjust = 0)
  ) +
  guides(colour = guide_legend(title = "region"))
print(scatter)
dev.off()

关键说明

  • 自定义转换包含正向和反向函数,ggplot会通过反向转换将转换后的坐标映射回原始速率值,因此轴标签显示的是真实数据,点的位置则是经过对数转换后的结果,解决偏斜问题的同时保证可读性。
  • 对于值为0的情况,log(0+1)=0,所以0在图中的位置保持不变,符合预期。
  • 自定义的breaks函数可以根据数据分布调整刻度数量和范围,你可以按需修改。

内容的提问来源于stack exchange,提问作者WellWellWell

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 12:47:49