使用for循环生成ggplot2分面图时各分面hlines均相同问题求助
问题原因
你的代码存在两个核心错误:
- 每次循环都调用
facet_wrap(~ Machine)生成全部分面,同时仅添加当前循环对应设备的3条全局水平线,循环执行完成后整张图会叠加所有设备的水平线,所有分面都会显示全部水平线,自然数值完全一致。 - 额外的
print()调用会导致循环执行多少次就输出多少张重复的图表,完全冗余。
解决方法
ggplot2的分面功能本身就支持匹配分组汇总值,不需要使用for循环,直接给geom_hline传入你已经汇总好的d1_split数据集即可,分面会自动根据分组变量Machine匹配对应数值,正确代码如下:
ggplot(d1, aes(x = Num, y = Cq, col = Machine)) + geom_point(size=2) + geom_line() + xlab(NULL) + ylab("Cq value") + facet_wrap(~ Machine, nrow = 2, ncol = 4) + # 传入汇总数据集,分面自动匹配对应设备的阈值线 geom_hline(data = d1_split, aes(yintercept = Avg), linetype="dashed", color="red") + geom_hline(data = d1_split, aes(yintercept = Upper_1), linetype="dashed", color="red") + geom_hline(data = d1_split, aes(yintercept = Lower_1), linetype="dashed", color="red") + theme(axis.text.x = element_text(colour = "black", angle = 45, vjust = 0.5), axis.title=element_text(size=16, colour = "black"), axis.text=element_text(size=14, colour = "black"), axis.line = element_line(colour = "black"), panel.background = element_blank(), legend.text = element_text(size=12), legend.title = element_text(size=14), legend.box.background = element_rect(colour = "black"))
如果确实需要用for循环实现单张单设备的图表(和基础plot输出逻辑一致),只需要去掉facet_wrap调用,并且每次循环筛选对应设备的子集绘图即可:
for(i in d1_split$Machine){ # 每次只筛选当前设备的数据绘图 plot_data <- d1[d1$Machine == i, ] threshold <- d1_split[d1_split$Machine == i, ] p <- ggplot(plot_data, aes(x = Num, y = Cq)) + geom_point(size=2, color = "black") + geom_line(color = "black") + xlab(i) + ylab("Cq value") + ylim(threshold$Lower_1 - 0.25, threshold$Upper_1 + 0.25) + geom_hline(yintercept = threshold$Avg, linetype="dashed", color="red") + geom_hline(yintercept = threshold$Upper_1, linetype="dashed", color="red") + geom_hline(yintercept = threshold$Lower_1, linetype="dashed", color="red") + theme(axis.text.x = element_text(colour = "black", angle = 45, vjust = 0.5), axis.title=element_text(size=16, colour = "black"), axis.text=element_text(size=14, colour = "black"), axis.line = element_line(colour = "black"), panel.background = element_blank(), legend.position = "none") print(p) }
内容的提问来源于stack exchange,提问作者Rnovice19
相关产品推荐
相关产品推荐

