将数据框pct值乘100后ggplot条形图为空的问题排查
问题
原本使用ggplot2绘制条形图显示正常,为了展示真实百分比,将数据框中pct列的值乘以100后,绘制的条形图变为空。以下是绘图代码和数据结构:
绘图代码
ggplot(remove_missing(mydata), mapping = aes(x = value, y = pct)) + geom_col(aes(fill = value), width = 0.30) + scale_y_continuous(lim=c(0,1),labels=scales::percent) + geom_text(aes(label=round(pct,1)), colour="black", size=3) + scale_fill_manual( values = c('option1' = "blue", 'option2' = "blue", 'option3' = "blue", 'option4' = "blue", 'option5' = "blue", 'option6' = "blue", 'option7' = "blue", 'option8' = "blue", 'option9' = "blue", 'option10' = "blue", 'option11' = "blue", 'option12' = "blue", 'option13' = "blue"), drop = FALSE) + labs(x = "", y = "pct of responders") + guides(fill = "none") + theme( plot.margin = margin(t = 0, r = 30, b = 20, l = 5.5), plot.title = element_text(size = 15, face = "plain"), panel.background = element_blank(), panel.grid.major = element_line(colour = "grey"), panel.grid.major.x = element_blank(), panel.grid.minor = element_line(colour = "lightgrey"), axis.ticks.x = element_blank(), axis.ticks.y = element_line(colour = "grey"), axis.text.y = element_text( size = 11, face = "plain", hjust = 0 ), axis.text.x = element_text( size = 11, face = "plain", hjust = 0 ), axis.title.x = element_text(size = 12), ) + coord_flip() + ggtitle("") + scale_x_discrete(labels = function(x) str_wrap(x, width = 20))
数据结构
structure(list(variable = c("option1", "option1", "option10", "option10", "option11", "option11", "option12", "option12", "option13", "option13", "option2", "option2", "option3", "option3", "option4", "option4", "option5", "option5", "option6", "option6", "option7", "option7", "option8", "option8", "option9", "option9"), value = structure(c(1L, NA, 10L, NA, 11L, NA, 12L, NA, 13L, NA, 2L, NA, 3L, NA, 4L, NA, 5L, NA, 6L, NA, 7L, NA, 8L, NA, 9L, NA), .Label = c("option1", "option2", "option3", "option4", "option5", "option6", "option7", "option8", "option9", "option10", "option11", "option12", "option13" ), class = c("ordered", "factor")), n = c(98L, 49L, 107L, 40L, 59L, 88L, 46L, 101L, 9L, 138L, 133L, 14L, 50L, 97L, 98L, 49L, 138L, 9L, 103L, 44L, 37L, 110L, 84L, 63L, 14L, 133L), pct = c(66.6666666666667, 33.3333333333333, 72.7891156462585, 27.2108843537415, 40.1360544217687, 59.8639455782313, 31.2925170068027, 68.7074829931973, 6.12244897959184, 93.8775510204082, 90.4761904761905, 9.52380952380952, 34.0136054421769, 65.9863945578231, 66.6666666666667, 33.3333333333333, 93.8775510204082, 6.12244897959184, 70.0680272108844, 29.9319727891156, 25.1700680272109, 74.8299319727891, 57.1428571428571, 42.8571428571429, 9.52380952380952, 90.4761904761905)), class = c("grouped_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, -26L), groups = structure(list( variable = c("option1", "option10", "option11", "option12", "option13", "option2", "option3", "option4", "option5", "option6", "option7", "option8", "option9"), .rows = structure(list( 1:2, 3:4, 5:6, 7:8, 9:10, 11:12, 13:14, 15:16, 17:18, 19:20, 21:22, 23:24, 25:26), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame" ), row.names = c(NA, -13L), .drop = TRUE))
原因及解决方案
原因
问题出在y轴刻度范围的设置:
- 原始数据中
pct是0-1的小数(比如0.666对应66.6%),此时scale_y_continuous(lim=c(0,1))的范围刚好匹配,条形图正常显示。 - 当你把
pct乘以100后,数值变成了66.6、33.3这类0-100的整数,但y轴范围仍被限制在0-1,所有条形的高度都超出了显示区域,所以看起来是空图。
解决方案
有两种可行方式,任选其一即可:
- 调整y轴范围:将
scale_y_continuous的lim参数改为c(0,100),同时保留labels=scales::percent(它会自动把100转换为100%显示)。 - 不修改原始数据:直接用
scales::percent格式化y轴标签,它会自动把0.666这类小数转换成66.6%,不需要手动乘以100,仅在文本标签中对pct做乘100处理即可。
推荐第二种方式,避免修改原始数据,以下是调整后的代码:
ggplot(remove_missing(mydata), mapping = aes(x = value, y = pct)) + geom_col(aes(fill = value), width = 0.30) + # 保留原y轴范围,scales::percent自动转换小数为百分比格式 scale_y_continuous(lim=c(0,1), labels=scales::percent) + # 文本标签显示百分比,需将pct乘以100后保留一位小数 geom_text(aes(label=round(pct*100,1)), colour="black", size=3) + scale_fill_manual( values = rep("blue",13), # 简化重复的颜色设置 drop = FALSE) + labs(x = "", y = "pct of responders") + guides(fill = "none") + theme( plot.margin = margin(t = 0, r = 30, b = 20, l = 5.5), plot.title = element_text(size = 15, face = "plain"), panel.background = element_blank(), panel.grid.major = element_line(colour = "grey"), panel.grid.major.x = element_blank(), panel.grid.minor = element_line(colour = "lightgrey"), axis.ticks.x = element_blank(), axis.ticks.y = element_line(colour = "grey"), axis.text.y = element_text(size = 11, face = "plain", hjust = 0), axis.text.x = element_text(size = 11, face = "plain", hjust = 0), axis.title.x = element_text(size = 12) ) + coord_flip() + ggtitle("") + scale_x_discrete(labels = function(x) str_wrap(x, width = 20))
若选择第一种修改数据的方式,仅需将scale_y_continuous(lim=c(0,1))改为scale_y_continuous(lim=c(0,100), labels=scales::percent)即可。
内容的提问来源于stack exchange,提问作者Espejito
相关产品推荐
相关产品推荐

