R
可视化
ggplot2
Author

Rui

Published

October 14, 2022

来源:http://r-graph-gallery.com/line-chart-dual-Y-axis-ggplot2.html

导入程序包

Code
library(tidyverse)
library(ggplot2)
library(dplyr)
library(patchwork) # 拼接两幅图
library(hrbrthemes)

创建虚拟数据

Code
data <- data.frame(
  day = as.Date("2019-01-01") + 0:99,
  temperature = runif(100) + seq(1, 100)^2.5 / 10000,
  price = runif(100) + seq(100, 1)^1.5 / 10
)

data %>% head() %>% knitr::kable()
day temperature price
2019-01-01 0.9210156 100.56474
2019-01-02 0.3817453 99.47352
2019-01-03 0.7530957 97.75718
2019-01-04 0.7020752 95.69686
2019-01-05 0.0907566 94.44658
2019-01-06 0.1273013 93.49653

基础绘图

Code
p1 <- ggplot(data, aes(x=day, y=temperature)) +
  geom_line(color = "seagreen", size = 2) +
  ggtitle("Temperature: range 1-10") +
  theme_ipsum()
  
p2 <- ggplot(data, aes(x=day, y=price)) +
  geom_line(color = "tomato", size = 2) +
  ggtitle("Price: range 1-100") +
  theme_ipsum()

# 使用patchwork程序包进行拼接
p1 + p2

双 Y 轴

使用 sec.axis() 来添加第二个坐标轴。

Note

sec.axis(trans=~.*10, name="Second Axis") 中的 trans=~.*10 是指对第一个坐标轴刻度乘以 10 作为第二个坐标轴的刻度。这个系数 10 是怎么确定的呢?由上图可知:以变量 price 为第二坐标轴的刻度几乎是以 temperature 为第一坐标轴的刻度的 10 倍。

Code
ggplot(data, aes(x=day, y=temperature)) +
  
  # 自定义Y轴
  scale_y_continuous(
    
    # 第一个坐标轴
    name = "First Axis",
    
    # 添加第二个坐标轴
    sec.axis = sec_axis(trans=~.*10, name="Second Axis")
  ) +
  theme_ipsum()

使用双 Y 轴作图

Code
coeff <- 10 # 设置比例系数
temperatureColor <- "seagreen"
priceColor <- "tomato"

ggplot(data, aes(x=day)) +
  
  geom_line( aes(y=temperature), size=2, color=temperatureColor) + 
  geom_line( aes(y=price / coeff), size=2, color=priceColor) + 
  # 除以10以保证与temperature有相同的尺度
  
  scale_y_continuous(
    
    # 第一坐标轴
    name = "Temperature (Celsius °)",
    
    # 第二坐标轴
    sec.axis = sec_axis(~.*coeff, name="Price ($)")
  ) +
  
  theme(
    axis.title.y = element_text(color = temperatureColor, size=13),
    axis.title.y.right = element_text(color = priceColor, size=13)
  ) +

  ggtitle("Temperature down, price up")

Note

在添加 geom_line 的时候为什么还要将 price 除以 coeff?虽然设置了第二坐标轴,但实际上第二坐标轴只是一个“注释”,图整体的网格线还是以第一坐标轴的尺度显示的。所以必须要将第二个变量除以比例系数来保证与第一个变量的尺度相同。