You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ggplot2带偏移双Y轴的刻度范围与标签配置技术咨询

How to Create a Dual Y-Axis Plot with Custom Scales, Labels, and Offset in ggplot2

Got it, let's break down how to replicate that Spreen et al. 2008-style dual Y-axis plot with ggplot2—since you already have the basics down, we'll focus on the key customizations you need: distinct scale ranges, custom labels, and that offset Y-axis layout.

Core Concept

First, remember that ggplot2 doesn't natively support dual Y-axes (the team discourages them for readability), but we can work around it by scaling one dataset to fit the range of the other, then adding a secondary axis that reverses that scaling. The offset effect is handled via theme adjustments to shift the right axis away from the plot area.

Step 1: Prepare Your Data

Let's use a sample time series dataset to demonstrate—say we have two variables with very different ranges:

  • temperature: ranges 0–25°C
  • flow_rate: ranges 0–100 m³/s
library(ggplot2)
library(dplyr)

# Sample time series data
set.seed(123)
df <- tibble(
  date = seq(as.Date("2000-01-01"), as.Date("2000-12-31"), by = "week"),
  temperature = rnorm(53, mean = 15, sd = 5),
  flow_rate = rnorm(53, mean = 50, sd = 15)
)

Step 2: Calculate Scaling Factor for the Secondary Variable

To align the second dataset with the first Y-axis range, calculate a scaling factor:

# Get range of primary Y variable (temperature)
temp_range <- range(df$temperature, na.rm = TRUE)
# Get range of secondary Y variable (flow_rate)
flow_range <- range(df$flow_rate, na.rm = TRUE)

# Scaling factor: map flow_range to temp_range
scale_factor <- diff(temp_range) / diff(flow_range)

# Scale the flow_rate data to fit temp_range
df <- df %>%
  mutate(flow_scaled = (flow_rate - flow_range[1]) * scale_factor + temp_range[1])

Step 3: Build the Plot with Custom Axes and Offset

Now we'll add both layers, define the secondary axis, and adjust the theme to create the offset effect:

ggplot(df, aes(x = date)) +
  # Primary Y-axis layer (temperature)
  geom_line(aes(y = temperature), color = "darkblue", linewidth = 1) +
  # Secondary Y-axis layer (scaled flow_rate)
  geom_line(aes(y = flow_scaled), color = "darkred", linewidth = 1) +
  
  # Define primary Y-axis
  scale_y_continuous(
    name = "Temperature (°C)",
    breaks = seq(0, 25, 5),
    limits = temp_range
  ) +
  
  # Define secondary Y-axis: reverse the scaling to show original flow values
  scale_y_continuous(
    sec.axis = sec_axis(
      ~ (. - temp_range[1]) / scale_factor + flow_range[1],
      name = "Flow Rate (m³/s)",
      breaks = seq(0, 100, 20)
    ),
    # Reuse primary axis limits to keep alignment
    limits = temp_range
  ) +
  
  # Theme adjustments for offset Y-axis
  theme_classic() +
  theme(
    # Shift right axis title and labels left to create offset
    axis.title.y.right = element_text(margin = margin(l = -20)),
    axis.text.y.right = element_text(margin = margin(l = -20)),
    # Optional: adjust tick length for the right axis to match offset
    axis.ticks.length.y.right = unit(-5, "pt"),
    # Add legend to clarify which line maps to which axis
    legend.position = "top"
  ) +
  # Add labels for clarity
  labs(x = "Date") +
  # Manually add legend (since we used aes without group)
  scale_color_manual(values = c("darkblue", "darkred"), labels = c("Temperature", "Flow Rate")) +
  guides(color = guide_legend(title = "Variable"))

Key Customizations Explained

  • Dual Scale Ranges: The sec_axis() function uses the inverse of our scaling factor to convert the scaled data back to the original flow_rate values, so the right axis shows the correct range.
  • Custom Labels: We explicitly set breaks and name for both axes to match your desired labels.
  • Offset Effect: The margin parameter in axis.title.y.right and axis.text.y.right shifts the right axis elements left, creating that staggered look from the Spreen et al. paper. Adjust the l (left margin) value to tweak the offset distance.

Important Note

While this works, keep in mind that ggplot2's developers discourage dual Y-axes because they can easily mislead readers about correlations between variables. If possible, consider faceting your plots instead—but if you need to replicate the specific layout from the paper, this method will get you there.

内容的提问来源于stack exchange,提问作者BBB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 18:34:09