对数刻度绘图中扩展Y轴添加内边距以避免底部点被裁剪
解决ggplot2对数刻度下0值数据点被裁剪的问题
当使用scale_y_log10(limits=c(0.01, NA))时,由于log10(0)无意义,且ggplot默认的超出范围(oob)处理逻辑会删除所有y≤0.01的点,导致原始数据中的0值点被裁剪。以下是三种可行的解决办法:
方案一:修改0值为小正数+使用squish函数
将原始数据中的0替换为略低于y轴下限的小数值,再用scales::squish将超出范围的点压缩到轴边界,既能保留点的显示,又不破坏对数刻度的整体效果:
require(data.table) require(ggplot2) require(scales) dt1 <- data.table(time=c(0,31,150,230,300), value=c(2,0.2,0,0,10)) dt1[, result:=ifelse(value>0,'POSITIVE','NEGATIVE')] # 替换0为0.005(略低于下限0.01) dt1[, value := ifelse(value == 0, 0.005, value)] p1 <- ggplot(dt1, aes(x=time, y=value, fill=result, group=1)) + geom_line() + geom_point(size=3, shape=21) + scale_fill_manual(values = c('white','black')) + scale_y_log10(limits=c(0.01, NA), oob=squish) print(p1)
方案二:使用伪对数变换(pseudo_log)
伪对数变换在数值接近0时采用线性变换,远离0时切换为对数变换,天然支持0值,无需修改原始数据:
require(data.table) require(ggplot2) dt1 <- data.table(time=c(0,31,150,230,300), value=c(2,0.2,0,0,10)) dt1[, result:=ifelse(value>0,'POSITIVE','NEGATIVE')] p1 <- ggplot(dt1, aes(x=time, y=value, fill=result, group=1)) + geom_line() + geom_point(size=3, shape=21) + scale_fill_manual(values = c('white','black')) + scale_y_continuous(trans='pseudo_log', limits=c(0.01, NA)) print(p1)
方案三:自定义OOB函数
如果不想修改原始数据,可以自定义超出范围的处理函数,将低于下限的点强制设置为下限值,从而保留点的显示:
require(data.table) require(ggplot2) dt1 <- data.table(time=c(0,31,150,230,300), value=c(2,0.2,0,0,10)) dt1[, result:=ifelse(value>0,'POSITIVE','NEGATIVE')] p1 <- ggplot(dt1, aes(x=time, y=value, fill=result, group=1)) + geom_line() + geom_point(size=3, shape=21) + scale_fill_manual(values = c('white','black')) + scale_y_log10(limits=c(0.01, NA), oob=function(x, limits) pmax(pmin(x, limits[2]), limits[1])) print(p1)
内容的提问来源于stack exchange,提问作者Vasily A
相关产品推荐
相关产品推荐

