如何让ggplot2对数转换后的X轴从0开始并正确缩放?
问题描述
使用ggplot2绘制Gapminder数据集的人均GDP(gdpPercap)与预期寿命(lifeExp)散点图,要求经过对数转换的X轴从0开始并正确缩放。当前代码如下:
主绘图代码
xbreaks <- c(0, 10000, 20000, 30000, 40000, 50000) popbreaks <- rev(c(3, 10, 30, 100, 300)*1000000) ### Golden Scatter attempt p1 <- ggplot(data = mainData, mapping = aes(x= gdpPercap, y = lifeExp, color = continent)) p <- p1 + goldenScatterCAtheme+ geom_point(alpha = 0.55, aes(size=pop)) + scale_x_log10(breaks= xbreaks, labels= xbreaks/1000) + scale_color_brewer(palette = "Set1") + scale_size(breaks = popbreaks) + labs(x = "GDP per Capita", y = "Life Expectancy in Years") p <- p + guides(size = FALSE) #p <- p + scale_x_continuous(expand = c(0, 0), limits = c(0,NA)) width <- 7 ggsave("ggScatterHw1.pdf", width = width, height = width/1.618)
自定义主题代码
goldenScatterCAtheme <- theme( panel.background = element_rect(fill = "white"), aspect.ratio = ((1 + sqrt(5))/2)^(-1), axis.ticks.length = unit(0.5, "char"), #Horizontal axis.line.x.top = element_line(size = 0.1), axis.line.x.bottom = element_line(size = 0.1), axis.ticks.x = element_line(size = 0.1), axis.text.x = element_text(color = "gray45", size = 12), axis.title.x = element_text(size = 12, margin = margin(t = 7.5, r = 0, b = 0, l = 0)), #Vertical axis.ticks.y = element_line(size = 0.1), axis.text.y = element_text(color = "gray45", size = 12, margin = margin(t = 0, r = 0, b = 0, l = 0)), axis.title.y = element_text(size = 12, margin = margin(t = 0, r = 7.5, b = 0, l = 0)), #Legend legend.key = element_rect(fill = NA, color = NA), #GridLines panel.grid.major.x = element_line(color = "gray95", size = 0.2), panel.grid.major.y = element_line(color = "gray95", size = 0.2), #Faceting strip.background = element_blank(), strip.text.x = element_text(size = 12), strip.text.y = element_blank(), strip.placement = "outside", panel.spacing.x = unit(1.25, "lines"), panel.spacing.y = unit(1, "lines") ) class(goldenScatterCAtheme)
当前图表效果:
解决方案
对数函数在x=0处无定义,直接用scale_x_log10无法将轴起点设为0,可通过以下两种方法实现需求:
方法1:伪对数转换(推荐)
伪对数转换可处理0值,同时对大数保持对数缩放特性,适合让轴从0开始且保留对数缩放的场景:
scale_x_continuous( trans = scales::pseudo_log_trans(sigma = 100), # sigma控制0附近线性区域宽度,可按需调整 breaks = xbreaks, labels = xbreaks/1000, expand = c(0, 0), limits = c(0, NA) )
sigma参数:数值越小,0附近线性区域越窄;针对Gapminder的gdpPercap数据,设为100能让缩放更自然。expand = c(0,0)和limits = c(0,NA)确保轴起点对齐0。
方法2:视觉模拟0起点(保留纯对数转换)
若坚持使用纯对数转换,可通过调整轴扩展和断点标签,视觉上模拟轴从0开始:
scale_x_log10( breaks = xbreaks[-1], # 移除无效的0断点 labels = c("0", xbreaks[-1]/1000), # 手动添加0的标签 expand = expansion(mult = c(0.05, 0)), # 向左扩展轴范围,靠近0 limits = c(min(mainData$gdpPercap)/2, NA) # 设下限为数据最小值的一半,避免截断点 )
此方法仅视觉上接近0,实际对数轴仍从正数开始,适合严格需要纯对数缩放的场景。
完整修改代码(方法1)
xbreaks <- c(0, 10000, 20000, 30000, 40000, 50000) popbreaks <- rev(c(3, 10, 30, 100, 300)*1000000) p1 <- ggplot(data = mainData, mapping = aes(x= gdpPercap, y = lifeExp, color = continent)) p <- p1 + goldenScatterCAtheme+ geom_point(alpha = 0.55, aes(size=pop)) + scale_x_continuous( trans = scales::pseudo_log_trans(sigma = 100), breaks = xbreaks, labels = xbreaks/1000, expand = c(0, 0), limits = c(0, NA) ) + scale_color_brewer(palette = "Set1") + scale_size(breaks = popbreaks) + labs(x = "GDP per Capita", y = "Life Expectancy in Years") p <- p + guides(size = FALSE) width <- 7 ggsave("ggScatterHw1.pdf", width = width, height = width/1.618)
内容的提问来源于stack exchange,提问作者Kenzie DeKeyser
相关产品推荐
相关产品推荐

