scale transformation中的trans
参数
以可视化log转换的结果为例说明ggplot2是如何实现的:
# mpg为original data , p0为original data的可视化 ,p1和p2为两种实现方式
p0 <- ggplot(mpg,aes(displ,cty)) + geom_point() + labs(title="original mpg")
p1 <- ggplot(mpg,aes(displ,log10(cty))) + geom_point() + labs(title="change mpg")
p2 <- ggplot(mpg,aes(displ,cty)) + geom_point() + scale_y_continuous(trans="log10") + labs(title="scale transformation")
p3 <- ggplot(mpg,aes(displ,cty)) + geom_point() + coord_trans(x="log10",y="log10") + labs(title="coord_trans()")
ggpubr::ggarrange(p0,p1,p2,p3,ncol=1)
p1
和p2
除了纵坐标labels,其他看起来一模一样。两者的区别是:相对于p0
,p1
直接对original data(mpg
)进行transformat(改变了original data),p2
通过scale进行transformat(不改变original data)。
总结下来是:要实现坐标轴的log转换,对data进行log转换是必须的。p1
和p2
的区别其实是可视化实现方式(显式转换和隐式转换)的区别。在log转换后的可视化结果中,坐标轴相同breaks处只是labels的区别,实际对应的数值是相同的,也就是对p2
来说,真实的数值被带上了"面具",”面具“与真实数值之间是一一对应关系。
为什么推荐p2
?便于与p0
比较,可以看到log转换后哪些更细微的差别被显示出来。
you use a transformed scale, the axes will be labelled in the original data space; if you transform the data, the axes will be labelled in the transformed space
相对于p0
,p3
所做的事情是original data不变,使坐标轴不再是一个线性数轴,而是经过log转换的数轴,因此这种转换可能会改变几何对象的形状。另外,breaks的位置会变,但实际对应的值,也就是labels跟p0
是一样的。
Regardless of which method you use, the transformation occurs before any statistical summaries. To transform after statistical computation use coord_trans()
在少数情况下,ggplot2为了简化,提供了几种常用transformation的函数:scale_x/y_log10()
、scale_x/y_reverse()
、scale_x/y_sqrt()
。所以以下命令等价:
p4 <- ggplot(mpg,aes(displ,cty)) + geom_point() + scale_x_log10()
p5 <- ggplot(mpg,aes(displ,cty)) + geom_point() + scale_x_continuous(trans="log10")
trans
参数的可选项如下:
transformation由transfer执行,一个transfer描述transformation及其逆转换以及如何绘制labels。以下命令等价:
p5 <- ggplot(mpg,aes(displ,cty)) + geom_point() + scale_x_continuous(trans="log10")
p6 <- ggplot(mpg,aes(displ,cty)) + geom_point() + scale_x_continuous(trans=scales::log10_trans())
可以用trans_new()
构建自己的transfer:
trans_new(
name, # transformation name
transform, # 函数或函数名,用来执行transformation
inverse, # 函数或函数名,用来执行逆转换
breaks = extended_breaks(), # default breaks function
minor_breaks = regular_minor_breaks(), # default minor breaks function
format = format_format(), # default format
domain = c(-Inf, Inf)
)
查看log_trans()
的源代码:
> log_trans
function (base = exp(1))
{
force(base)
trans <- function(x) log(x, base)
inv <- function(x) base^x
trans_new(paste0("log-", format(base)), trans, inv, log_breaks(base = base),
domain = c(1e-100, Inf))
}