R ggplot2分面排名柱状图标注柱顶原始值报错解决
ggplot2 柱图添加顶标报错修复
问题描述
需要基于d_ranked_long数据集绘制柱高为rank的柱状图,在每个柱体上方标注d_long$value中对应排名的原始绝对值。在ggplot代码中添加geom_text(data = d_long, aes(x=parameter, label=value))语句后运行报错,报错信息如下:
Error in `f()`: ! Aesthetics must be valid data columns. Problematic aesthetic(s): y = rank. Did you mistype the name of a data column or forget to add after_stat()? Backtrace: 1. base `<fn>`(x) 2. ggplot2:::print.ggplot(x) 4. ggplot2:::ggplot_build.ggplot(x) 5. ggplot2 by_layer(function(l, d) l$compute_aesthetics(d, plot)) 6. ggplot2 f(l = layers[[i]], d = data[[i]]) 7. l$compute_aesthetics(d, plot) 8. ggplot2 f(..., self = self)
当前绘图效果示例:
预期效果:匹配d_ranked_long中每个(x,y)坐标位置,抓取d_long中对应位置的value值放置在柱顶,例如第一个分面(vs = 0, am = 0)的第一根柱顶应标注3.44,第二根柱顶标注8.00,以此类推。
报错原因
- ggplot2的图层默认继承
ggplot()函数内定义的全局美学映射,全局映射中设置了y=rank,但geom_text()单独指定的数据源d_long里不存在rank字段,图层找不到对应美学变量直接触发报错。 - 就算手动给
geom_text()补全y轴映射,两个独立数据集如果没有通过分面变量、x轴分类变量做精确对齐,很容易出现标签和柱子错位的问题,分面场景下出错概率极高。
修复方案
最稳妥的实现方式是 提前把需要标注的原始值合并到排名数据集,从根源避免跨数据集映射的继承问题和匹配错位问题,可复现完整代码如下:
library(tidyverse) # 1. 构建示例数据 d_wide <- head(mtcars) %>% rownames_to_column(var = "make_model") %>% select(!c(make_model,gear, carb)) # 2. 转换为存储原始绝对值的长格式数据 d_long <- d_wide %>% pivot_longer(!c(vs, am), names_to = "parameter", values_to = "value") # 3. 计算排名并存储为独立数据框 d_ranked <- data.frame(d_wide [,c(8:9)], t(apply(d_wide[,-c( 8:9)], 1, rank, ties.method='min'))) # 4. 转换为存储排名值的长格式数据 d_ranked_long <- d_ranked %>% pivot_longer(!c(vs, am), names_to = "parameter", values_to = "rank") # 5. 指定x轴刻度顺序 d_ranked_long$parameter <- factor(d_ranked_long$parameter, levels = c("wt", "cyl", "drat", "hp", "disp", "qsec","mpg")) d_long$parameter <- factor(d_long$parameter, levels = c("wt", "cyl", "drat", "hp", "disp", "qsec","mpg")) # 合并两个数据集,按分面变量+x轴变量精确对齐行 d_plot <- merge(d_ranked_long, d_long, by = c("vs", "am", "parameter")) # 6. 绘图 d_plot %>% ggplot(aes(x=parameter, y=rank)) + geom_col() + # 等价于geom_bar(stat = "identity"),写法更简洁 # 直接调用合并后数据的value列做标签,vjust调整标签位置到柱顶上方 geom_text(aes(label=value), vjust = -0.3, size = 3.5) + facet_grid(am ~ vs) + scale_y_continuous(expand = expansion(mult = c(0, 0.1))) + # 给顶部标签留出显示空间 theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))
效果说明
运行代码后即可实现预期效果:每个柱体高度对应rank值,柱顶正确标注对应位置的原始绝对值,无错位、无报错。
内容的提问来源于stack exchange,提问作者hnguyen
相关产品推荐
相关产品推荐

