You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何在geom_line()图表中控制日期(X轴)间隔,隐藏休市时段

解决港股时间序列图休市时段线条问题的方案

嗨,我完全懂你的困扰——用连续时间轴画股市数据时,午间休市、隔夜休市的空白区间会被线条强行连接,让图表看起来乱糟糟的。下面我一步步帮你搞定这个问题,同时实现从周一开始显示数据的需求。

步骤1:加载必要工具包

咱们用tidyverse处理数据,lubridate简化时间格式处理,比手动写format参数省心太多:

library(tidyverse)
library(lubridate)

步骤2:数据预处理与清洗

先读取并整理你的数据,统一列名、转换时间格式,同时提取日期、当日时间和交易时段(早市/午市):

# 读取数据,统一列名(解决你数据中列名不一致的问题)
hongkongstocks <- read.csv(file="Data/hong-kong-stocks-copy.csv", stringsAsFactors = FALSE) %>%
  rename(Hang.Seng = `Hang Seng`) # 把"Hang Seng"重命名为统一的"Hang.Seng"

# 转换时间格式,提取关键时间字段
hongkongstocks <- hongkongstocks %>%
  mutate(
    datetime = mdy_hm(Date), # 自动解析"月/日/年 时:分"格式的时间
    date = date(datetime), # 提取纯日期部分
    time = hms::as_hms(datetime), # 提取当天的时间(不含日期)
    # 标记交易时段:早市9:30-12:00,午市13:00-16:00
    session = case_when(
      time >= hms::as_hms("09:30:00") & time <= hms::as_hms("12:00:00") ~ "morning",
      time >= hms::as_hms("13:00:00") & time <= hms::as_hms("16:00:00") ~ "afternoon",
      TRUE ~ "off"
    )
  ) %>%
  filter(session != "off") # 过滤掉非交易时段的数据(如果有的话)

# 创建分组ID:每个交易日的每个交易时段单独分组,避免休市时段的线条连接
hongkongstocks <- hongkongstocks %>%
  mutate(group_id = paste(date, session, sep = "_"))

步骤3:过滤出周一及之后的数据

按照你的需求,只保留周一及之后的交易日(wday()函数返回2代表周一,1代表周日):

hongkongstocks_filtered <- hongkongstocks %>%
  filter(wday(date) >= 2)

步骤4:绘制无休市连接的图表

方案1:单图显示,自动断开休市时段

通过group = group_id让ggplot为每个交易时段单独绘制线条,午休和隔夜的空白就不会被连接:

ggplot(hongkongstocks_filtered, aes(x = datetime, y = Hang.Seng, group = group_id)) +
  geom_line(color = "#0066cc") +
  # 设置x轴显示格式,每小时一个刻度
  scale_x_datetime(
    date_labels = "%m/%d/%y %H:%M",
    breaks = scales::date_breaks("1 hour")
  ) +
  labs(
    x = "日期时间",
    y = "恒生指数",
    title = "港股日内走势(无休市时段连接)"
  ) +
  theme_minimal() +
  # 旋转x轴标签,避免重叠
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

方案2:按日期分面显示(更清晰)

如果希望每个交易日的走势单独展示,分面的方式会更直观:

ggplot(hongkongstocks_filtered, aes(x = time, y = Hang.Seng, group = date)) +
  geom_line(color = "#0066cc") +
  # 按日期分面,每个日期一个子图
  facet_wrap(~date, ncol = 1) +
  # 设置x轴显示当天时间,每小时一个刻度
  scale_x_time(
    labels = scales::time_format("%H:%M"),
    breaks = scales::time_breaks("1 hour")
  ) +
  labs(
    x = "当日时间",
    y = "恒生指数",
    title = "港股日内走势(按日期分面)"
  ) +
  theme_minimal()

为什么这个方案有效?

之前的图表出现长线条,是因为ggplot把整个时间轴当成连续区间,会自动连接所有数据点。通过给每个交易日的每个交易时段设置独立分组ID,ggplot会为每个分组单独绘制线条,不同分组之间不会产生连接,自然就隐藏了休市时段的空白。

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

火山引擎 最新活动