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

在ggplot中为个体经纬度轨迹图添加日期/月份次坐标轴

在ggplot经纬度轨迹图添加日期/月份次X轴的实现方案

核心思路

通过线性映射将主X轴(经度/累积距离)的数值范围与日期的时间戳范围建立一一对应关系,利用ggplot的sec_axis参数生成关联的次轴,无需分面或专用运动包。


步骤1:数据预处理

首先确保日期时间格式正确,并计算用于映射的基础范围值:

library(tidyverse)

# 读取数据并处理日期时间
d <- read.csv("Sample_Data.csv") %>%
  # 根据你的实际DateTime格式调整format参数,比如"%Y/%m/%d %H:%M"
  mutate(DateTime = as.POSIXct(DateTime, format = "%Y-%m-%d %H:%M:%S")) %>%
  arrange(DateTime)

# 计算全局日期范围(用于后续映射)
date_min <- min(d$DateTime)
date_max <- max(d$DateTime)

方案1:以经度为主X轴,添加日期次轴

适合轨迹大致沿经度方向移动、无明显往返的场景:

# 计算经度范围
lon_min <- min(d$Longitude)
lon_max <- max(d$Longitude)

# 定义经度转日期的映射函数
lon_to_date <- function(lon) {
  # 将经度区间线性映射到日期时间戳区间
  date_num <- as.numeric(date_min) + (lon - lon_min) * (as.numeric(date_max) - as.numeric(date_min)) / (lon_max - lon_min)
  as.POSIXct(date_num, origin = "1970-01-01")
}

# 定义日期转经度的反向函数(用于确定次轴刻度位置)
date_to_lon <- function(date) {
  lon_min + (as.numeric(date) - as.numeric(date_min)) * (lon_max - lon_min) / (as.numeric(date_max) - as.numeric(date_min))
}

# 绘制带次轴的轨迹图
trial1 <- ggplot(d, aes(x = Longitude, y = Latitude)) +
  geom_path() +
  geom_point(size = 0.5) +
  coord_cartesian() +
  theme_bw() +
  scale_x_continuous(
    name = "经度",
    sec.axis = sec_axis(
      trans = ~ lon_to_date(.),
      name = "日期",
      # 按月设置次轴刻度
      breaks = date_to_lon(seq(date_min, date_max, by = "month")),
      # 格式化刻度标签为"月份 年份"
      labels = function(x) format(lon_to_date(x), "%b %Y")
    )
  )

print(trial1)

方案2:以累积距离为主X轴,添加日期次轴

适合轨迹有往返、经度非单调变化的场景,时空逻辑更清晰:

# 计算累积移动距离(需geosphere包)
library(geosphere)
d <- d %>%
  mutate(
    # 计算相邻点的球面距离(单位:米)
    distance = c(0, distHaversine(cbind(Longitude, Latitude)[-nrow(.), ], 
                                  cbind(Longitude, Latitude)[-1, ])),
    # 转换为公里并计算累积距离
    cumulative_distance = cumsum(distance) / 1000
  )

# 计算累积距离范围
dist_min <- min(d$cumulative_distance)
dist_max <- max(d$cumulative_distance)

# 定义累积距离转日期的映射函数
dist_to_date <- function(dist) {
  date_num <- as.numeric(date_min) + (dist - dist_min) * (as.numeric(date_max) - as.numeric(date_min)) / (dist_max - dist_min)
  as.POSIXct(date_num, origin = "1970-01-01")
}

# 定义日期转累积距离的反向函数
date_to_dist <- function(date) {
  dist_min + (as.numeric(date) - as.numeric(date_min)) * (dist_max - dist_min) / (as.numeric(date_max) - as.numeric(date_min))
}

# 绘制带次轴的轨迹图
trial2 <- ggplot(d, aes(x = cumulative_distance, y = Latitude)) +
  geom_path() +
  geom_point(size = 0.5) +
  coord_cartesian() +
  theme_bw() +
  scale_x_continuous(
    name = "累积距离 (km)",
    sec.axis = sec_axis(
      trans = ~ dist_to_date(.),
      name = "日期",
      breaks = date_to_dist(seq(date_min, date_max, by = "month")),
      labels = function(x) format(dist_to_date(x), "%b %Y")
    )
  )

print(trial2)

关键注意事项

  • 若轨迹存在往返,方案1的次轴日期会出现顺序混乱,优先选择方案2。
  • 需根据实际数据调整as.POSIXct的format参数,确保DateTime列转换正确。
  • 可修改seq()的by参数调整次轴刻度间隔(如by = "week"按周显示)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 22:55:18