R|ggplot2(三)|coord 系列函数坐标轴转换

浏览: 3220

coord_ 系列函数可以改变xy轴的位置,默认使用 coord_cartesian(),我们可以改变成如下几种

coord_cartesian  默认情况,指定参数则控制图形特定区域放大显示
coord_fixed 图形伸缩变换
coord_flip 横纵坐标位置转换
coord_polar 弯曲横纵坐标(画饼图可以用)
coord_map 将地图变成球状展示(这个我们以后讲到地图再专门说)
coord_trans 转化数据

coord系列函数只影响图形展示,不影响内部数据的值。即使用原数据作图,再对图形进行变动

coord_cartesian(xlim = NULL, ylim = NULL, expand = TRUE)

如果不加参数,就是默认的图形,和不加这个函数一样

  • xlim 和 ylim 各接一个二元数值向量,控制显示的区域范围,原理不是截取,而是放大该区域,原有图形不变,超出此范围的点也可以照常显示
  • expand 为T则默认指定xlim轴两端还留一些空隙,F则控制范围即为图形的边缘
library(ggplot2)
p0 <- ggplot(mtcars, aes(wt, drat)) + geom_point()
p0
p0 + coord_cartesian() # 没有变化
p0 + coord_cartesian(xlim = c(2, 4))
p0 + coord_cartesian(xlim = c(2, 4), expand = F)

1.jpg

coord_fixed(ratio = 1, xlim = NULL, ylim = NULL, expand = TRUE)

其他参数和上面相同,ratio表示纵轴1单位显示的长度,是横轴1单位显示的长度的几倍。比如xy轴都是0-5cm的数据,ratio=2则图形高和宽的比是2:1,即纵轴的1cm显示出来的长度是横轴的两倍。所以ratio越小,图形越扁

p0
p0 + coord_fixed(ratio = 1)
p0 + coord_fixed(ratio = 1/2)
p0 + coord_fixed(ratio = 2)

2.jpg

coord_flip(xlim = NULL, ylim = NULL, expand = TRUE)

横纵轴位置互换,没有特殊参数

p0
p0 + coord_flip()

1.jpg

coord_polar(theta = "x", start = 0, direction = 1)

上面我们提到过如何使用这个函数将柱状图转化为饼图,现在我们对这个图形的参数进行简单调整

  • start 接一个弧度制角度,看饼图起始点放在哪个角度上
  • direction默认为1,各个元素顺时针排列下去,如果是-1则逆时针
pp <- ggplot(mpg, aes(1, fill=class))+geom_bar()
pp
pp + coord_polar(theta = "y")
pp + coord_polar(theta = "y", start = pi/3)
pp + coord_polar(theta = "y", direction = -1)

1.jpg

其实我们会发现,做出来的图形虽然样子像饼图,但是标度什么的都不尽如人意,都需要后期使用其他方法调整,可以看出ggplot2包对饼图的支持是不强的,这个Hadley本人对饼图的排斥也有关系,饼图绝大多数都可以使用柱状图代替。

coord_trans(x = "identity", y = "identity", limx = NULL, limy = NULL, xtrans, ytrans)

将数据转换为想要的形式,再进行作图,最常见的是取对数。它跟scale_x_log10()函数还是有区别的。

  • 后者等价于先将数据取对数,再拿进来处理
  • 前者则是其他处理优先,最后作图时再取对数。
    我们拿拟合曲线举例子
  • 我们如果用scale_x_log10就相当于把x的数据取了对数放进来做回归,拟合出一条直线。
  • 如果使用coord_trans则是先用原有数据进行回归,得到一条拟合直线之后再变换坐标轴
a <- seq(-5,2,len=30) + abs(rnorm(30,0,0.1))
b <- exp(seq(-5,2,len=30)) + abs(rnorm(30,0,0.1)) + 10
df <- data.frame(a,b)
ps <- ggplot(df, aes(a,b)) + geom_point() +
coord_fixed(ratio=1)+
geom_smooth(method="lm")
ps

# 使用log之后的y来做
ggplot(df, aes(a,log10(b))) + geom_point() +
coord_fixed(ratio=1)+
geom_smooth(method="lm")

# 同上
ps + scale_y_log10()

# 使用coord_trans
# ps + coord_trans(y = "log10") # 因为拟合出的曲线y出现负值,所以无法对y取对数,此处报错
# 我们可以取其中一部分来做
df1 <- df[df$a>0,]
ggplot(df1, aes(a,b)) + geom_point() +
coord_fixed(ratio=1)+
geom_smooth(method="lm") +
coord_trans(y="log10")

1.jpg

我们发现使用coord_trans时,拟合出来的曲线发生了弯曲。那是因为是先使用原有数据拟合出了一条直线,之后再改变坐标轴作图,所以曲线也被弯曲了。这不同于直接对数据进行变换的情况。

下面我们讨论当我们需要进行其他变换时应该怎么做。

我们需要使用scales包

library(scales)
pt <- ggplot(df, aes(a,b)) + geom_point() +
coord_fixed(ratio=1)
pt
pt + coord_trans(y="log10")

ggplot(df, aes(a,b)) + geom_point() +
coord_fixed(ratio=1)+
coord_trans(x=exp_trans(exp(1)))

下面使用的exp_trans函数相当于把x轴取了e的指数,这是scales包中的函数,查看exp_trans函数源码

function (base = exp(1)) 
{
trans_new(paste0("", format(base)),
function(x) base^x,
function(x) log(x, base = base))
}
<environment: namespace:scales>

我们可以看到,这是由此包中的trans_new函数创建出来的,所以为了更灵活地使用这种变换,我们需要学习trans_new函数。

我们需要看trans_new函数的参数,而为了了解它参数的含义,我们可以去查看它的源码。我们发现这个函数作用后返回一个list,结合ggplot2的使用,则相当于ggplot2在调用list中的一些元素,我们可以知道调用时哪些参数才是真正重要的。我们主要使用transform/inverse/domain三个参数

  • transform 接一个函数,数据要作为参数输入,表用怎么使用数据x
  • inverse 输入transform 的反作用函数
  • domain 接一个二元数值向量,表明只对这个范围之内的数据实行这种变换
  • name参数是什么都无所谓(但是必须要有),其实在这里inverse参数是什么也无所谓

接下来,我们再注意一个细节

ggplot(df, aes(exp(a),b)) + geom_point()
ggplot(df, aes(a,b)) + geom_point() +
coord_trans(x=exp_trans(exp(1)))

1.jpg

这两个图形状相同,但是要注意x轴标度不同,前者就是使用转化之后数值作为标度,而后者则是使用原来数值作为标度,而标度之间的距离却被扭曲了,这正是coord类函数所做的事情,只是对轴进行更改,数据都是原来的没有变化。

正因为此,所以当我们自己用 trans_new 函数创建变化时,像加减乘除这样的运算,就不会对图形有任何更改。因为这样没有改变点之间的密集分布情况,压缩下来还是一样。

推荐 0
本文由 dwzb 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册