如何让geom_col条形从底部延伸且保留反转y轴(仿Strava跑步图)
问题描述
想要模仿Strava样式绘制跑步数据,使用ggplot2的geom_col绘图时,希望条形从底部而非顶部延伸,同时保留反转的y轴(配速值越高代表速度越低)。
原始代码如下:
library(ggplot2) df <- data.frame(km = 1:20, avePace = c(321, 301, 319, 312, 312, 313, 305, 309, 313, 341, 352, 352, 355, 355, 372, 362, 372, 363, 340, 316)) ggplot(data = df, aes(x=km, y = avePace, fill = avePace)) + geom_col(show.legend = FALSE, orientation="x") + scale_fill_distiller() + scale_y_reverse(labels = function(t) strftime(t, "%M:%S")) + coord_cartesian(ylim = c(7*60, 3*60 )) + ylab("Pace (min/km)")
当前图表效果:
期望的图表样式类似Strava的配速条形图:
已发现该问题与同类问题一致,但无法复现现有解决方案。
解决方案
核心是调整条形的起始位置与高度计算逻辑:反转y轴后,geom_col默认从y=0开始绘制,而我们需要让条形从y轴下限(最慢配速,即7分钟对应的420秒)向上延伸至实际配速值。
修改后的代码如下:
library(ggplot2) df <- data.frame(km = 1:20, avePace = c(321, 301, 319, 312, 312, 313, 305, 309, 313, 341, 352, 352, 355, 355, 372, 362, 372, 363, 340, 316)) # 定义y轴上下限(单位:秒) y_min <- 7*60 # 对应y轴底部的最慢配速(7min/km) y_max <- 3*60 # 对应y轴顶部的最快配速(3min/km) ggplot(data = df, aes(x = km)) + # 用geom_rect手动控制条形范围,替代geom_col geom_rect( aes( xmin = km - 0.4, xmax = km + 0.4, # 模拟geom_col的条形宽度 ymin = y_min, ymax = avePace, # 条形从y轴底部延伸至实际配速 fill = avePace ), show.legend = FALSE ) + scale_fill_distiller() + scale_y_reverse( labels = function(t) strftime(as.POSIXct(t, origin = "1970-01-01"), "%M:%S"), limits = c(y_min, y_max) ) + ylab("配速 (min/km)") + xlab("公里数") + theme_minimal()
关键修改说明:
- 替换
geom_col为geom_rect:直接控制每个条形的起始(ymin=y_min)和终止(ymax=avePace)位置,确保条形从y轴底部向上延伸。 - 明确
scale_y_reverse的limits参数:替代coord_cartesian,更适配当前条形位置的计算逻辑。 - 调整x轴矩形范围:通过
km±0.4模拟geom_col默认的条形宽度,保持视觉一致性。
此方案可实现Strava风格的配速条形图:条形从最慢配速(y轴底部)向上延伸至当前公里的实际配速,同时y轴保持反转(速度越快,配速值越低,位置越靠上)。
内容的提问来源于stack exchange,提问作者Jimmie
相关产品推荐
相关产品推荐

