ggplot2绘制分组小提琴图异常,如何正确展示连续变量分布?
解决小提琴图绘制异常的问题
问题背景
尝试用以下代码基于取值范围1-5的var_y变量为两个分组绘制小提琴图:
p <- ggplot(df, aes(var_group, var_y)) p + geom_violin()
图表显示异常,疑似数据未正确绘制或变量未被识别为连续变量。已执行df$var_y <- as.numeric(as.character(df$var_y))确保变量为数值型,但问题仍未解决。使用另一取值范围1-10的原生数值变量按相同方法绘制的小提琴图显示正常,因此对当前图表存在疑问,希望能清晰展示变量整体分布的小提琴图。
数据集为长格式,每个id对应70条记录,完整数据集约4200行,样本数据如下:
df <- structure(list(id = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), var_group = c("A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B"), var_y = c(3, 4, 5, 2, 3, 3, 2, 2, 3, 4, 2, 2, 3, 4, 5, 4, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 4, NA, 4, 5, 5, 3, 4, 2, 4, 4, 4, 4, NA, 4, 4, 4, 4, 4, NA, 3, NA, 4, 5, 4, NA, NA, 4, 5, 5, 3, NA, 4, 4, 4, 5, 5, 5, 4, 5, 1, 1, NA, NA, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, NA, 2, 2, 1, 1, 1, 1, NA, 2, 1, 1, 2, 1, 1, 1, 2, 1, 2, NA, 1, 1, 1, 2, 1, 1, 1, 1, 1)), class = "data.frame", row.names = c(211L, 212L, 213L, 214L, 215L, 216L, 217L, 218L, 219L, 220L, 221L, 222L, 223L, 224L, 225L, 226L, 227L, 228L, 229L, 230L, 231L, 232L, 233L, 234L, 235L, 236L, 237L, 238L, 239L, 240L, 241L, 242L, 243L, 244L, 245L, 246L, 247L, 248L, 249L, 250L, 251L, 252L, 253L, 254L, 255L, 256L, 257L, 258L, 259L, 260L, 261L, 262L, 263L, 264L, 265L, 266L, 267L, 268L, 269L, 270L, 271L, 272L, 273L, 274L, 275L, 276L, 277L, 278L, 279L, 280L, 421L, 422L, 423L, 424L, 425L, 426L, 427L, 428L, 429L, 430L, 431L, 432L, 433L, 434L, 435L, 436L, 437L, 438L, 439L, 440L, 441L, 442L, 443L, 444L, 445L, 446L, 447L, 448L, 449L, 450L, 451L, 452L, 453L, 454L, 455L, 456L, 457L, 458L, 459L, 460L, 461L, 462L, 463L, 464L, 465L, 466L, 467L, 468L, 469L, 470L, 471L, 472L, 473L, 474L, 475L, 476L, 477L, 478L, 479L, 480L, 481L, 482L, 483L, 484L, 485L, 486L, 487L, 488L, 489L, 490L))
问题原因与解决方案
原因分析
var_y是取值仅为1-5的离散数值型变量,小提琴图默认的核密度估计对这类离散数据的拟合效果很差,导致图形异常。而取值1-10的变量因为取值更分散,核密度估计能正常生成,所以图表显示正常。
解决方案
方案1:调整核密度估计的带宽
手动设置更小的带宽,让密度估计更贴合离散数据的分布:
library(ggplot2) ggplot(df, aes(var_group, var_y)) + geom_violin(adjust = 0.5) + # 调整adjust参数,值越小带宽越窄 scale_y_continuous(breaks = 1:5) # 显示所有1-5的刻度
方案2:结合箱线图或散点图展示离散分布
小提琴图对离散数据的表现力有限,建议叠加箱线图或散点图补充信息:
ggplot(df, aes(var_group, var_y)) + geom_violin(adjust = 0.5) + geom_boxplot(width = 0.1, fill = "white") + # 叠加箱线图展示分位数 scale_y_continuous(breaks = 1:5)
或者用散点图展示原始数据分布:
ggplot(df, aes(var_group, var_y)) + geom_jitter(width = 0.2, alpha = 0.3) + # 抖动散点避免重叠 geom_violin(alpha = 0.2, adjust = 0.5) + scale_y_continuous(breaks = 1:5)
方案3:改用更适合离散数据的图表
如果小提琴图不是必须的,可使用柱状图展示每个取值的频数分布:
ggplot(df, aes(var_y, fill = var_group)) + geom_histogram(binwidth = 1, position = "dodge") + facet_wrap(~var_group) + scale_x_continuous(breaks = 1:5)
内容的提问来源于stack exchange,提问作者Karolina
相关产品推荐
相关产品推荐

