ggplot函数画双Y轴图

何时画双Y轴图

一般的,我们可以通过通过不同颜色渲染,来展示两个或多个变量之间的协同变化。例如,下面这张图, 累积平衡蒸散发、蒸散发和降水都是以毫米为单位的,而且他们数量级差距不大,那么我们就可以通过用不同颜色渲染来把他们放到一张图里可视化,便于对比。
在这里插入图片描述

但常常我们遇到的却不是这种情况,当我们想对比两个变量的变化关系(Covariate),但是两个变量之间的数量级差距太大,我们无法让他们共用一个Y轴的时候。例如我们想表示温度和降水之间的关系,温度的在年尺度范围大概是-30~30度,而在年尺度上降水量是一个求和量,100到1000不等,两个数据共用一个y轴的时候年际降水变得很大,温度可能就成了一天很矮的线了,看不到温度的变化(如下图,我把蒸散发的单位从mm换成了kg m-2 s-1)。当然我们可以计算相关系数用一个值来表示他们之间的相关关系,但是如果我们想可视化的方式,来分析具体的时间点上的变化趋势之间有什么关系呢?这就要用到双Y轴图了
请添加图片描述

双折线图

R语言 ggplot2包中提供画双Y轴图的方法。其实他没有提供一个比较方便的解决方案,但是这个包中有一个可以用于我们篡改第二Y轴(也就是右边的Y轴)外观和各种参数的函数。这就需要我们想办法来使两个数据尽可能能对比来展示,所以我们需要对第二个Y轴展示的变量进行缩放变化。听起来复杂,做起来简单,直接上代码:

ggplot(data = DF_CN_Cha_subset, aes(x = TIMESTAMP, y = NETRAD)) +
  geom_line(col = '#2c3781') +
  geom_point(col = '#2c3781') +
  geom_line(aes(y = (TA_F+25)*5), col = '#e10000') +
  geom_point(aes(y = (TA_F+25)*5), col = '#e10000') +
  scale_y_continuous(name = 'Net Radiation(W/m²)',
                     sec.axis = sec_axis(~./5-25,name="T(°C)")) +
  theme_classic()

这是一个可视化净辐射(W/m²)和气温(ºC)之间协变化的图。

ggplot(data = DF_CN_Cha_subset, aes(x = TIMESTAMP, y = NETRAD)) +
  geom_line(col = '#2c3781') +
  geom_point(col = '#2c3781')

先把代码拆开看,首先ggplot的data参数是我们画图用的数据框,注意第一个aes参数中y轴设置我们的主Y轴的变量,这里可以是净辐射,也可以是气温。然后我们画出点和线,现在这张图长这个样子在这里插入图片描述

接着我们画温度的曲线,记得我刚刚说了,我们需要做一个温度的变化,这里我给温度做了个线性变化, t e m p v i s = a ∗ ( t e m p + b ) temp_{vis}=a*(temp+b) tempvis=a(temp+b),这里的a是5,b是25,为什么选这样的系数呢?

summary(DF_CN_Cha_subset$TA_F)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
-25.042  -5.652   6.356   4.730  16.072  23.894 
summary(DF_CN_Cha_subset$NETRAD)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 -30.36   22.26   62.50   71.44  115.33  195.95 

因为经过统计,发现温度的分布在-25~25之间,而辐射的值在-30~200之间,那么我就想给温度加一个25就在0~50之间,再乘以5就差不多时0~250之间,这样两者就可以对比了。我们加上这两行代码继续再看看效果在这里插入图片描述

这是不是就有些感觉了,但是我们还没加上第二个Y轴,加上第二个Y轴就是加一行代码,用到的函数是scale_y_continuous(),这个函数功能很多,可以用来改主Y轴的标题,ticks,以及标签等。其下有个参数是sec.axis,需要赋值为sec_axis函数创建的对象,这个对象的第一个参数是变化,也就是这个Y轴要相对于主Y轴进行怎么样的变化,有人会问这里为什么又要进行变化?

scale_y_continuous(name = 'Net Radiation(W/m²)',
                     sec.axis = sec_axis(~./5-25,name="T(°C)"))

其实,因为刚刚我们对温度进行了变化,所以如果不做任何变化的话,sec_axis参数会自动复制净辐射的坐标轴,画出来的图是下面这个样子。
在这里插入图片描述

很明显,温度数据不可能到200的,所以我们要在这里做一个和刚刚运算步骤相反的变化,刚刚是先+25再乘5这次我们要倒过来,先除5再减25就能反回刚刚那个样子了。也代码中看到的~./5-25,这个.代表的是原来的Y轴,如果你想之前的变化做的是这样的 t e m p v i s = a ∗ t e m p + b temp_{vis}=a*temp+b tempvis=atemp+b, 你得先减b再除a,那么你应该输入~(.-b)/a而不是(~.-b)/a,我之前就犯过这样的错误,错把~.当成一个整体了,实际上~相当于表达式的等号,来让R后台知道这是一个表达式。现在我们画出来的图长这样。
在这里插入图片描述

感觉好像缺了点Y轴风格,调调代码让他变得更学术把!最后我调了一下,把整个第二Y轴的颜色调成和温度一样的颜色

ggplot(data = DF_CN_Cha_subset, aes(x = TIMESTAMP, y = NETRAD)) +
  geom_line(col = '#2c3781') +
  geom_point(col = '#2c3781')+
  geom_line(aes(y = (TS_F_MDS_1+25)*5), col = '#e10000') +
  geom_point(aes(y = (TS_F_MDS_1+25)*5), col = '#e10000')+
  scale_y_continuous(name = 'Net Radiation(W/m²)',
                     sec.axis = sec_axis(~./5-25,name="T(°C)"))+
  theme_classic()+
  theme(axis.title.y.right = element_text(color='#e10000'),
        axis.line.y.right = element_line(color='#e10000'),
        axis.text.y.right = element_text(color='#e10000'),
        axis.ticks.y.right = element_line(color='#e10000'))

在这里插入图片描述

当然你也可以这样,只让数字变色。

  theme(axis.title.y.right = element_text(color='#e10000'),
        axis.text.y.right = element_text(color='#e10000'),
        axis.title.y.left = element_text(color='#2c3781'),
        axis.text.y.left = element_text(color='#2c3781'),
        )

在这里插入图片描述

柱状和折线双Y图

名字是瞎取的,效果如下,原理相同,给出代码,自己琢磨。
在这里插入图片描述

ggplot(data = DF_CN_Cha_subset, aes(x = TIMESTAMP, y = P_F, group = 1)) +
  geom_bar(position = "identity", stat = "identity", col = 'black', fill = 'black')+
  geom_line(aes(y = SWC_F_MDS_1), col = 'orange') +
  geom_point(aes(y = SWC_F_MDS_1), col = 'orange') +
  scale_y_continuous(name = 'Precipitation(mm)',expand = c(0,0),
                     limits = c(0,45),
    sec.axis = sec_axis(~. * 0.01,name="SWC(%)")) +
  theme_classic()+
  theme(axis.title.y.right = element_text(color="orange"),
        axis.line.y.right = element_line(color="orange"),
        axis.text.y.right = element_text(color="orange"),
        axis.ticks.y.right = element_line(color="orange"))

以上就是画双Y轴图的一些个人探索,看完觉得有帮助的,求赞,求关注!

🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧🐧

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值