使用ggplot2绘制森林图报错及添加数据列的技术求助
问题1:初始森林图报错修复
报错原因
代码仅添加了参考线,但未绘制任何对应数据的几何对象(如点、线段),导致ggplot无法识别y轴的有效映射,触发报错;同时多余的scale_y_discrete设置也干扰了因子水平的识别。
修复后代码
library(ggplot2) library(ggpubr) # 数据赋值 basdai_data <- structure(list(explanatory_variables = structure(1:15, levels = c("Age", "Disease duration", "Smoking", "BMI", "HLA-B27", "Uveitis", "TNFi start year", "csDMARD", "CRP", "Psoriasis", "Arthritis", "NSAID", "Enthesitis", "TNFi type", "IBD"), class = "factor"), unadj_coef = c(0.93, 0.92, 1.13, 1, 1.02, 1.32, 0.93, 0.83, 0.76, 1.42, 1.77, 0.04, 1.26, 0.93, 1.3), adj_coef = c(0.91, 0.91, 1.13, 1, 1.02, 1.33, 0.92, 0.83, 0.76, 1.42, 1.77, 0.04, 1.26, 0.93, 1.3), pct_change = c(-1.8, -0.9, 0.6, -0.5, 0.4, 0.3, -0.2, -0.2, 0.1, 0.1, 0.1, -0.1, -0.1, 0, 0)), row.names = c(NA, -15L), class = "data.frame") # 按pct_change绝对值降序排序 basdai_data <- basdai_data[order(abs(basdai_data$pct_change), decreasing = TRUE),] # 重新排序因子水平 basdai_data$explanatory_variables <- factor(basdai_data$explanatory_variables, levels = as.character(basdai_data$explanatory_variables)) # 绘制森林图 ggplot(basdai_data, aes(x = pct_change, y = explanatory_variables)) + geom_vline(xintercept = 0, linetype = "dashed", color = "gray50") + geom_point(size = 3, color = "#2c3e50") + # 添加数据点 scale_x_continuous(breaks = seq(-3, 3, 1)) + labs(x = "Percentage change", y = "Explanatory variable") + theme_pubr() + theme(text = element_text(size = 15, family = "Calibri"), axis.title = element_text(size = 20))
问题2:森林图前添加数据列
通过geom_text在不同x坐标位置添加各列数据,同时扩展x轴范围容纳文本:
ggplot(basdai_data, aes(y = explanatory_variables)) + # 可选:添加灰色背景行 geom_hline(aes(yintercept = as.integer(explanatory_variables)), linewidth = 1.5, color = "gray90") + # 左侧数据列文本 geom_text(aes(x = -5, label = explanatory_variables), hjust = 0, size = 4) + geom_text(aes(x = -2, label = unadj_coef), size = 4) + geom_text(aes(x = 0, label = adj_coef), size = 4) + geom_text(aes(x = 2, label = pct_change), size = 4) + # 森林图部分 geom_vline(xintercept = 4, linetype = "dashed", color = "gray50") + geom_point(aes(x = 4 + pct_change), size = 3, color = "#2c3e50") + # 设置x轴 scale_x_continuous(breaks = c(-5, -2, 0, 2, 4), labels = c("Variable", "Unadj. coef.", "Adj. coef.", "Change (%)", ""), limits = c(-6, 7)) + labs(x = NULL, y = NULL) + theme_pubr() + theme(text = element_text(size = 15, family = "Calibri"), axis.text.x = element_text(face = "bold"), axis.ticks = element_blank())
问题3:p2图的离散值报错修复
报错原因是y = explanatory_variables为离散因子,但geom_hline使用了连续数值的yintercept,两者不兼容。解决方法是将y轴转换为连续变量,同时保留原标签:
# 数据赋值 basdai_level3 <- structure(list(explanatory_variables = c("Age", "TNFi type", "TNFi start year", "CRP", "Smoking", "Disease duration", "HLA-B27", "NSAID", "csDMARD", "BMI", "Uveitis", "Psoriasis", "IBD", "Arthritis", "Enthesitis"), ID = c(11753, 11753, 11753, 8661, 9991, 8063, 7074, 5204, 6776, 6585, 5635, 5541, 5601, 3955, 4903), countries = c(15, 15, 15, 13, 14, 11, 14, 10, 15, 13, 10, 10, 10, 9, 9), unadj_coef = c(0.67, 0.67, 0.67, 0.38, 0.84, 0.59, 0.78, -0.2, 0.66, 0.75, 1.1, 1.2, 1.08, 1.56, 1.03), adj_coef = c(0.61, 0.67, 0.66, 0.38, 0.86, 0.56, 0.79, -0.2, 0.65, 0.74, 1.12, 1.2, 1.08, 1.57, 1.03), change = c(-0.06, 0, 0, 0, 0.02, -0.03, 0.02, 0, -0.01, -0.01, 0.02, 0, 0, 0, 0), pct_change = c(-8.9, 0.4, -0.4, 1.2, 2.3, -4.7, 2.3, -0.4, -1.3, -1.4, 1.4, 0.4, -0.1, 0.2, -0.4), unadj_coef_pvalue = c(0.037, 0.037, 0.037, 0.319, 0.016, 0.138, 0.054, 0.689, 0.125, 0.072, 0.017, 0.01, 0.02, 0.004, 0.039), adj_coef_pvalue = c(0.058, 0.037, 0.038, 0.314, 0.013, 0.158, 0.048, 0.69, 0.13, 0.076, 0.016, 0.01, 0.02, 0.003, 0.039), interaction = c(NA, NA, NA, NA, NA, NA, -2.46, NA, NA, NA, NA, 5.07, NA, NA, NA)), row.names = c(NA, 15L), class = "data.frame") # 排序数据 basdai_level3 <- basdai_level3[order(basdai_level3$pct_change, decreasing = TRUE),] # 转换因子为连续数值,保留原标签 basdai_level3$y_pos <- as.integer(factor(basdai_level3$explanatory_variables, levels = as.character(basdai_level3$explanatory_variables))) y_labels <- basdai_level3$explanatory_variables names(y_labels) <- basdai_level3$y_pos # 绘制p2图 p2 <- ggplot(basdai_level3, aes(x = 1, y = y_pos)) + geom_hline(yintercept = basdai_level3$y_pos, linewidth = 13, color = "gray92") + geom_text(aes(label = explanatory_variables), hjust = 0) + geom_text(aes(x = 3, label = unadj_coef)) + geom_text(aes(x = 4, label = adj_coef)) + geom_text(aes(x = 5, label = pct_change)) + geom_text(aes(x = 6, label = ifelse(is.na(interaction), "", interaction))) + # 处理NA值 scale_x_continuous(NULL, breaks = c(1, 3, 4, 5, 6), limits = c(1, 7), labels = c('Variable', 'Unadj. coef.', 'Adj. coef.', 'Change (%)', 'Interaction'), position = 'top') + scale_y_continuous(NULL, breaks = basdai_level3$y_pos, labels = y_labels) + theme_void() + theme(axis.text.x.top = element_text(hjust = c(0, 0.5, 0.5, 0.5), face = "bold", family = "Calibri"), axis.text.y = element_text(hjust = 1)) print(p2)
内容的提问来源于stack exchange,提问作者Pashtun
相关产品推荐
相关产品推荐

