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

使用facet分面时,如何用geom_line连接geom_point的点?

问题描述

我遇到了一个未在网络上找到解决方案的问题,希望能得到相关提示。
我有一个数据集,其x轴为离散型,原本可以连接各点,但添加facet分面选项后,无法再跨分面连接点(例如周一夜班的最后一个点应连接到周二早班的点)。我找到了一个替代方案,但效果不佳。

可复现代码

# Create a simple dataset
dat <- data.frame(Days = c(rep("Monday", 6), rep("Tuesday", 6), rep("Wednesday", 6)),
                  Shift = rep(c("Morning", "Evening", "Night"), 6),
                  Group = c(rep("Group1", 3), rep("Group2", 3), rep("Group1", 3), rep("Group2", 3), rep("Group1", 3), rep("Group2", 3)),
                  Amount = c(6, 5, 6, 2, 3, 1, 5, 4, 6, 1, 2, 2, 5, 4, 7, 3, 1, 2)) 
# Change into factor to have the order I need
dat$Days <- factor(dat$Days, levels = c("Monday", "Tuesday", "Wednesday"))
dat$Shift <- factor(dat$Shift, levels = c("Morning", "Evening", "Night"))

# The plot I am stuck with
# The last dot of Monday night should be linked to Tuesday morning
ggplot(data = dat, aes(x = Shift, y = Amount)) + geom_point() +
    geom_line(aes(group = Group)) + facet_grid(.~Days) +
    theme(panel.spacing = unit(0, "lines"))

当前效果示意图:
当前效果示意图

替代方案(效果不佳)

# This is the alternative I found, but clearly not great
ggplot(data = dat, aes(x = interaction(Days, Shift, sep = "\n", lex.order = T), y = Amount)) + geom_point(aes(color = Group)) +
    geom_line(aes(group = Group)) +
    geom_vline(xintercept = c(3, 6, 9),
               color = "darkred", linetype = 2)

替代方案效果示意图:
替代方案效果示意图

解决方案

核心思路是将Days和Shift转换为连续的位置变量,让跨分面的点在连续轴上有对应位置,从而实现跨面板连线。

步骤1:构造连续位置变量

给每个Days-Shift组合分配连续数值,确保时间顺序正确:

# 生成所有Day-Shift的组合并按顺序排序
shift_order <- expand.grid(Days = levels(dat$Days), Shift = levels(dat$Shift))
shift_order <- shift_order[order(shift_order$Days, shift_order$Shift), ]
# 给每个组合分配连续位置
shift_order$x_pos <- 1:nrow(shift_order)
# 合并到原数据集
dat <- merge(dat, shift_order, by = c("Days", "Shift"))

步骤2:绘制带跨分面连线的图

利用连续的x_pos作为x轴,分面时设置scales="free_x"和space="free_x",同时手动调整x轴标签匹配原Shift名称:

library(ggplot2)

ggplot(dat, aes(x = x_pos, y = Amount)) +
  geom_point() +
  geom_line(aes(group = Group)) +
  # 分面,每个Day一个面板,x轴自由缩放且空间匹配
  facet_grid(. ~ Days, scales = "free_x", space = "free_x") +
  # 自定义x轴刻度和标签,仅显示当前面板对应Day的Shift
  scale_x_continuous(
    breaks = function(x) {
      current_day <- unique(dat$Days[dat$x_pos >= x[1] & dat$x_pos <= x[2]])
      panel_shifts <- shift_order[shift_order$Days == current_day, ]
      panel_shifts$x_pos
    },
    labels = function(x) {
      current_day <- unique(dat$Days[dat$x_pos >= x[1] & dat$x_pos <= x[2]])
      panel_shifts <- shift_order[shift_order$Days == current_day, ]
      panel_shifts$Shift
    }
  ) +
  theme(
    panel.spacing = unit(0, "lines"),
    axis.title.x = element_blank()
  )

该方案既保留了分面布局,又实现了跨分面的连续连线,同时x轴标签仍显示为原Shift名称,视觉效果更贴合需求。


内容的提问来源于stack exchange,提问作者Robin.N.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 04:55:02