在ggplot2中绘制不同值域多序列:如何清晰展示三者联动关系?
解决不同尺度变量的可视化问题:让LAF利率与NSE价格清晰联动展示
当然可以!当你面对数值尺度差异极大的变量时,有几种实用的方法能让所有序列的趋势都清晰呈现,同时保留它们之间的联动关系。下面我给你详细介绍三种方案:
方法1:使用双Y轴(Secondary Y-axis)
这是最直接的方案,将利率类变量(repo、revrepo)放在左侧Y轴,NSE价格放在右侧Y轴,各自使用适配自身范围的刻度,既能看到实际数值,又能直观对比趋势联动。
library(ggplot2) # 计算尺度转换的参数,用于将nse映射到repo/revrepo的范围 min_rate <- min(c(df_nse_1$repo, df_nse_1$revrepo)) max_rate <- max(c(df_nse_1$repo, df_nse_1$revrepo)) min_nse <- min(df_nse_1$nse) max_nse <- max(df_nse_1$nse) p_nse <- ggplot(df_nse_1) + # 绘制左侧Y轴的利率序列 geom_line(aes(x=Number, y=repo, color = "Repo"), size=1.4) + geom_line(aes(x=Number, y=revrepo, color = "Reverse Repo"), size=1.4) + # 绘制nse,先做线性转换适配左侧刻度范围 geom_line(aes(x=Number, y=(nse - min_nse)/(max_nse - min_nse)*(max_rate - min_rate) + min_rate, color = "nse"), size=1.4) + # 设置左侧Y轴(利率) scale_y_continuous( name = 'LAF rates (%)', limits = c(min_rate - 0.5, max_rate + 0.5), breaks = seq(5, 7, 0.5) ) + # 设置右侧Y轴(NSE价格),反向转换回原始数值 scale_y_continuous( sec.axis = sec_axis( trans = ~(. - min_rate)*(max_nse - min_nse)/(max_rate - min_rate) + min_nse, name = 'Estimated nse prices' ), name = 'LAF rates (%)', limits = c(min_rate - 0.5, max_rate + 0.5), breaks = seq(5, 7, 0.5) ) + scale_x_continuous(breaks = c(2,4,6,8,10))+ labs(color="Series") + xlab('\nNumber') + ggtitle("Estimated nse closing Prices given changes in LAF & CRR Rates") + theme( axis.text.x=element_text(size=12, color = "black"), plot.title = element_text(lineheight=.8, face="bold",colour = "black",hjust = 0.5,vjust = 2,size = 10), axis.title.y.right = element_text(color = "red"), # 右轴标题颜色与nse线条对应 legend.position = "top" ) + scale_color_manual(values = c("Repo"="blue", "Reverse Repo"="green", "nse"="red")) p_nse
方法2:数据归一化展示相对趋势
如果更关注变量间的相对变化联动而非实际数值,可以将所有变量缩放到[0,1]的范围,这样在同一Y轴上就能清晰看到趋势的同步性。
library(ggplot2) library(dplyr) # 需要用dplyr做数据转换 # 对三个变量做归一化处理 df_normalized <- df_nse_1 %>% mutate( repo_norm = (repo - min(repo))/(max(repo)-min(repo)), revrepo_norm = (revrepo - min(revrepo))/(max(revrepo)-min(revrepo)), nse_norm = (nse - min(nse))/(max(nse)-min(nse)) ) # 绘制归一化后的趋势图 p_normalized <- ggplot(df_normalized) + geom_line(aes(x=Number, y=repo_norm, color="Repo"), size=1.4) + geom_line(aes(x=Number, y=revrepo_norm, color="Reverse Repo"), size=1.4) + geom_line(aes(x=Number, y=nse_norm, color="nse"), size=1.4) + scale_x_continuous(breaks = c(2,4,6,8,10)) + labs( color="Series", y="Normalized Value (0-1)", x="\nNumber" ) + ggtitle("Normalized Trends of LAF Rates and NSE Prices") + theme( axis.text.x=element_text(size=12, color = "black"), plot.title = element_text(lineheight=.8, face="bold",colour = "black",hjust = 0.5,vjust = 2,size = 10) ) + scale_color_manual(values = c("Repo"="blue", "Reverse Repo"="green", "nse"="red")) p_normalized
方法3:分面绘图独立展示每个序列
如果希望最大化每个变量的细节展示,同时保留X轴的一致性以便对比,可以将三个序列分成独立的子图,每个子图使用自己的Y轴刻度。
library(ggplot2) library(tidyr) # 需要用tidyr将数据转为长格式 # 将宽格式数据转换为长格式,方便分面 df_long <- df_nse_1 %>% pivot_longer(cols = c(repo, revrepo, nse), names_to = "Series", values_to = "Value") # 绘制分面图 p_faceted <- ggplot(df_long, aes(x=Number, y=Value, color=Series)) + geom_line(size=1.4) + facet_wrap(~Series, scales = "free_y", ncol=1) + # 每个子图使用独立Y轴,纵向排列 scale_x_continuous(breaks = c(2,4,6,8,10)) + labs(x="\nNumber", y="Value") + ggtitle("Trends of LAF Rates and NSE Prices") + theme( axis.text.x=element_text(size=12, color = "black"), plot.title = element_text(lineheight=.8, face="bold",colour = "black",hjust = 0.5,vjust = 2,size = 10), strip.text = element_text(face="bold") # 子图标题加粗 ) + scale_color_manual(values = c("repo"="blue", "revrepo"="green", "nse"="red")) p_faceted
方案选择建议
- 若需要同时查看实际数值和联动关系,优先选择双Y轴方案;
- 若仅关注相对变化趋势的同步性,归一化方法更简洁直观;
- 若想完整展示每个变量的细节,分面绘图是最佳选择。
内容的提问来源于stack exchange,提问作者Nishant
相关产品推荐
相关产品推荐

