如何在ggplot时间序列图中添加TP变量的倒置柱状图
问题描述
我想优化现有的ggplot时间序列图,给TP(总降水量)变量添加倒置柱状图来提升可读性,但参考方案后效果不佳。期望最终效果用线条替代点,既能减少杂乱感,又能展示变量间的关联。以下是数据结构、示例数据和当前代码,求帮助:
数据结构
> str(DFSub0716) 'data.frame': 1633 obs. of 4 variables: $ datetime: POSIXct, format: "2016-07-06 12:00:00" "2016-07-06 13:00:00" ... $ Q_m3.s : num 0.396 0.396 ... $ No3_mg.l: num 1.72 1.5 ... $ TP : num 0.09661 0.06568 ...
示例数据
datetime Q_m3.s No3_mg.l TP 6703 2016-07-06 06:00:00 0.4430 1.566312 0.01118792 6704 2016-07-06 07:00:00 0.4195 1.609813 0.02158611 6705 2016-07-06 08:00:00 0.3960 1.628437 0.05844045 6706 2016-07-06 09:00:00 0.3960 1.683905 0.04606792 6707 2016-07-06 10:00:00 0.3960 1.617095 0.07120785 6708 2016-07-06 11:00:00 0.3960 1.634220 0.08015819 6709 2016-07-06 12:00:00 0.3960 1.724347 0.09661102 6710 2016-07-06 13:00:00 0.3960 1.495940 0.06567970 6711 2016-07-06 14:00:00 0.3960 1.488123 0.13109615 6712 2016-07-06 15:00:00 0.3960 1.494128 0.03369540 6713 2016-07-06 16:00:00 0.3960 1.482408 0.00210596 6714 2016-07-06 17:00:00 0.3960 1.509152 0.00052649 6715 2016-07-06 18:00:00 0.3960 1.483495 0.00000000
当前代码
#### 2016/07//06 DFSub060716 <- DFSub[DFSub$datetime >= "2016-07-06 06:00:00" & DFSub$datetime <= "2016-07-06 18:00:00", ] # to long format library(reshape2) DFSubL2 <- melt(DFSub060716, id="datetime") # x-axis breaks library(lubridate) desired_breaks2 <- seq.POSIXt(from = lubridate::ymd_hms("20160706 060000"), to = lubridate::ymd_hms("20160706 180000"), by = "2 hours") # scale and plot data library(ggplot2) library(dplyr) NQ060716 <- DFSubL2 %>% group_by(variable) %>% mutate( value.scaled = (value - mean(value)) / sd(value), idx = 1:n()) %>% ggplot(aes(x = datetime, y = value.scaled, colour = variable, linetype = variable)) + theme_bw() + theme( axis.title.x = element_blank(), panel.grid.major.x = element_blank())+ scale_x_datetime(date_labels = "%m.%d\n%H:%M", breaks = desired_breaks2)+ labs(title = "HND low-flow period 2016-07-06")+ geom_line(lwd = 0.9)+ scale_linetype_manual(values=c("solid", "solid", "solid")) + scale_color_manual(values = c("Q_m3.s" = "#000000", "No3_mg.l" = "#669933", "TP" = "#3399FF")) NQ060716
解决方案
核心思路是分开处理TP与其他变量:不将TP转为long格式,单独绘制倒置柱状图;其余变量保留标准化后的线条,既突出TP变化,又避免线条杂乱重叠。
优化后的代码如下:
#### 2016/07/06 数据筛选 DFSub060716 <- DFSub[DFSub$datetime >= "2016-07-06 06:00:00" & DFSub$datetime <= "2016-07-06 18:00:00", ] # 加载所需包 library(lubridate) library(ggplot2) library(dplyr) library(tidyr) # 生成x轴刻度 desired_breaks2 <- seq.POSIXt(from = ymd_hms("20160706 060000"), to = ymd_hms("20160706 180000"), by = "2 hours") # 对Q和No3进行标准化处理(TP单独处理) scaled_df <- DFSub060716 %>% select(datetime, Q_m3.s, No3_mg.l) %>% pivot_longer(cols = -datetime, names_to = "variable", values_to = "value") %>% group_by(variable) %>% mutate(value.scaled = (value - mean(value)) / sd(value)) # 绘制图形 ggplot() + # 绘制Q和No3的标准化线条 geom_line(data = scaled_df, aes(x = datetime, y = value.scaled, color = variable, linetype = variable), linewidth = 0.9) + # 绘制TP的倒置柱状图(取负值实现倒置) geom_col(data = DFSub060716, aes(x = datetime, y = -TP, fill = "TP"), width = 3600/1.2) + # width设为略小于小时间隔,避免柱子重叠 # 主题设置 theme_bw() + theme( axis.title.x = element_blank(), panel.grid.major.x = element_blank(), legend.title = element_blank() # 去掉图例标题 ) + # 坐标轴设置 scale_x_datetime(date_labels = "%m.%d\n%H:%M", breaks = desired_breaks2) + scale_y_continuous(name = "标准化值 / 倒置TP") + # 统一y轴标题 # 颜色和线型设置 scale_color_manual(values = c("Q_m3.s" = "#000000", "No3_mg.l" = "#669933")) + scale_fill_manual(values = c("TP" = "#3399FF")) + scale_linetype_manual(values = c("Q_m3.s" = "solid", "No3_mg.l" = "solid")) + # 标题 labs(title = "HND低流量时段 2016-07-06")
关键说明
- TP倒置实现:通过
y = -TP让柱状图向下延伸,调整width参数适配小时级时间间隔,避免柱子重叠。 - 变量分离处理:Q和No3保持标准化线条,TP用柱状图,既保留变量间的关联对比,又避免原long格式下的线条杂乱问题。
- 视觉一致性:沿用你原有的颜色和线型设置,同时优化图例,让整体更简洁。
内容的提问来源于stack exchange,提问作者JoSche
相关产品推荐
相关产品推荐

