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

如何在ggplot2中可视化营收与利润随时间的变化关系?

针对你的需求,这里有几个实用的可视化方案,既能清晰展示营收与利润随时间的变化趋势,又能直观体现两者的关联或背离关系:

先把原始数据整理成ggplot偏好的格式:

library(tidyverse)

# 构建数据集
df <- tibble(
  quarter = c("2020_Q1", "2020_Q2", "2020_Q3", "2020_Q4", "2021_Q1", "2021_Q2", "2021_Q3", "2021_Q4", "2022_Q1", "2022_Q2", "2022_Q3"),
  revenue = c(23700, 24400, 24000, 23300, 23800, 23600, 23100, 21800, 21600, 20700, 20100),
  profit = c(1426, 1447, 1245, 1599,  896,  813,  706,  510,  649,  789,  947)
) %>%
  # 转成长格式(部分方案需要)
  pivot_longer(cols = c(revenue, profit), names_to = "metric", values_to = "value")

1. 正确配置双Y轴(sec.axis 可正常生效)

你之前用sec.axis没生效,大概率是没对利润做缩放转换——因为营收和利润量级差太大,直接用次轴会导致利润线几乎贴在底部。解决方法是先把利润按比例缩放至营收的量级范围,再通过次轴反向转换显示原始利润值:

# 计算缩放系数:用营收最大值除以利润最大值
scale_factor <- max(df$revenue) / max(df$profit)

ggplot(df %>% filter(metric == "revenue"), aes(x = quarter, y = value, group = 1)) +
  geom_line(color = "#2c3e50", size = 1.2) +
  # 添加缩放后的利润线
  geom_line(data = df %>% filter(metric == "profit"), 
            aes(y = value * scale_factor), 
            color = "#e74c3c", size = 1.2) +
  # 设置主Y轴(营收)
  scale_y_continuous(
    name = "营收",
    # 设置次Y轴,反向缩放显示原始利润值
    sec.axis = sec_axis(~ . / scale_factor, name = "利润")
  ) +
  labs(x = "季度") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

优势:在同一图中同时展示两个指标的绝对值趋势,适合需要对比具体数值的场景;注意:双Y轴容易误导读者,需确保缩放逻辑清晰,标注明确。

2. 分面独立展示

把营收和利润分成上下两个子图,共享X轴,既能清晰看到各自趋势,又能直观对比两者的变化节奏:

ggplot(df, aes(x = quarter, y = value, group = 1)) +
  geom_line(color = "#2c3e50", size = 1.2) +
  facet_wrap(~ metric, ncol = 1, scales = "free_y") +
  labs(x = "季度", y = "") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

优势:完全避免双Y轴的误导性,每个指标的刻度独立,趋势展示更准确;适合侧重观察各自变化细节的场景。

3. 折线+柱状组合图

用折线展示营收,柱状展示利润(反之亦可),通过图形类型区分两个指标,无需次轴也能在同一图中对比:

# 转回宽格式数据做组合图
df_wide <- df %>% pivot_wider(names_from = metric, values_from = value)

ggplot(df_wide, aes(x = quarter)) +
  geom_line(aes(y = revenue, group = 1), color = "#2c3e50", size = 1.2) +
  geom_col(aes(y = profit * scale_factor), fill = "#e74c3c", alpha = 0.6) +
  scale_y_continuous(
    name = "营收",
    sec.axis = sec_axis(~ . / scale_factor, name = "利润")
  ) +
  labs(x = "季度") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

优势:图形类型的差异比颜色更直观,能快速区分两个指标;适合需要同时看绝对值和趋势的场景。

4. 标准化后同轴展示

将营收和利润都标准化到[0,1]范围,这样可以在同一Y轴上展示两者的相对变化趋势,重点看是否同步或背离:

df_normalized <- df %>%
  group_by(metric) %>%
  mutate(norm_value = (value - min(value)) / (max(value) - min(value))) %>%
  ungroup()

ggplot(df_normalized, aes(x = quarter, y = norm_value, color = metric, group = metric)) +
  geom_line(size = 1.2) +
  labs(x = "季度", y = "标准化值(0-1)", color = "指标") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

优势:忽略绝对值差异,聚焦趋势的同步性——比如营收持续下降,但利润在2022年开始回升,这个背离会非常明显;适合分析两者变化节奏的关联。

5. 散点图+趋势线(聚焦关联关系)

如果核心需求是看营收与利润的关联程度,可以用散点图展示每个季度的营收-利润对应关系,再添加趋势线看整体相关性:

ggplot(df_wide, aes(x = revenue, y = profit)) +
  geom_point(size = 3, color = "#2c3e50") +
  # 添加每个点的季度标签
  geom_text(aes(label = quarter), hjust = 1.2, vjust = 0.5) +
  # 拟合线性趋势线
  geom_smooth(method = "lm", se = FALSE, color = "#e74c3c") +
  labs(x = "营收", y = "利润") +
  theme_minimal()

优势:直接展示两个指标的相关性,同时通过标签看到时间维度的变化;适合分析“营收变化如何影响利润”的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 06:01:38