如何在ggplot分组柱状图中为每个x变量添加对应折线?
解决方案
问题分析
你遇到的问题主要有两个:
- 数据类型错误:通过
rbind字符向量创建的数据框,value和sd列是字符类型,无法被ggplot正确识别为数值进行绘图。 - 映射与分组错误:当前的x轴映射为
name,同时折线按interval分组,导致折线在不同name类别间连接;而你需要的是每个name对应一条折线,连接其在不同interval上的sd值,因此需要调整x轴和分组的映射逻辑。
修正后的完整代码
library(reshape2) library(dplyr) library(ggplot2) # 创建柱状图数据 df_bar <- as.data.frame( rbind( c('g1', 0.945131015, 1.083188828, 1.040164338, 1.115716593, 0.947886795), c('g2', 1.393211286, 1.264193745, 1.463434395, 1.298126006, 1.112718796), c('g3', 1.509976099, 1.450923745, 1.455102201, 1.280102338, 1.462689245), c('g4', 1.591697668, 1.326292649, 1.767207296, 1.623619341, 2.528108183), c('g5', 2.625114848, 2.164050167, 2.092843287, 2.301950359, 2.352736806) ) ) colnames(df_bar) <- c('interval', 'lvl3.Mellem.Høj', 'lvl1.Lav', 'TOM', 'lvl4.Høj', 'lvl2.Lav.Mellem') # 重塑数据并转换数值类型 df_bar <- melt(df_bar, id.vars = 'interval', variable.name = 'name', value.name = 'value') df_bar$value <- as.numeric(df_bar$value) # 创建折线数据 df_line <- as.data.frame( rbind( c('g1', 0.945131015 * 2, 1.083188828 * 2, 1.040164338 * 2, 1.115716593 * 2, 0.947886795 * 2), c('g2', 1.393211286 * 2, 1.264193745 * 2, 1.463434395 * 2, 1.298126006 * 2, 1.112718796 * 2), c('g3', 1.509976099 * 2, 1.450923745 * 2, 1.455102201 * 2, 1.280102338 * 2, 1.462689245 * 2), c('g4', 1.591697668 * 2, 1.326292649 * 2, 1.767207296 * 2, 1.623619341 * 2, 2.528108183 * 2), c('g5', 2.625114848 * 2, 2.164050167 * 2, 2.092843287 * 2, 2.301950359 * 2, 2.352736806 * 2) ) ) colnames(df_line) <- c('interval', 'lvl3.Mellem.Høj', 'lvl1.Lav', 'TOM', 'lvl4.Høj', 'lvl2.Lav.Mellem') # 重塑数据并转换数值类型 df_line <- melt(df_line, id.vars = 'interval', variable.name = 'name', value.name = 'sd') df_line$sd <- as.numeric(df_line$sd) # 合并数据 df <- inner_join(df_bar, df_line) # 绘制图形 ggplot(df, aes(x = interval)) + # 分组柱状图,按name填充,dodge排列 geom_bar(aes(y = value, fill = name), stat = 'identity', position = position_dodge(width = 0.9)) + # 折线图,按name分组,与柱子对齐 geom_line(aes(y = sd, group = name, color = name), position = position_dodge(width = 0.9)) + # 添加折线点,增强可读性 geom_point(aes(y = sd, group = name, color = name), position = position_dodge(width = 0.9)) + theme_bw()
关键调整说明
- 数据类型转换:添加
as.numeric()将字符型的value和sd转换为数值型,确保ggplot能正确解析数值数据。 - x轴与分组映射:将x轴设为
interval,折线按name分组,这样每个name会生成一条连接不同interval的折线。 - 位置对齐:使用
position_dodge(width = 0.9)让折线和点与对应的柱子对齐(geom_bar默认的dodge宽度为0.9)。
如果你的需求确实是x轴为name,每个name下的interval对应一条折线,可以使用以下代码:
ggplot(df, aes(x = name)) + geom_bar(aes(y = value, fill = interval), stat = 'identity', position = position_dodge(width = 0.9)) + geom_line(aes(y = sd, group = interval, color = interval), position = position_dodge(width = 0.9)) + geom_point(aes(y = sd, group = interval, color = interval), position = position_dodge(width = 0.9)) + theme_bw()
内容的提问来源于stack exchange,提问作者Mathias Nissen
相关产品推荐
相关产品推荐

