You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言小提琴图:如何保留均值实线并将分位数设为虚线?

Solution for Custom Split Violin Plot with Solid Mean & Dashed Quantiles

Hey there! I totally get where you're coming from—working with @jan-glx's custom split violin function can lead to accidentally uniform line styles for all statistical lines. Let's fix that so your mean line stays solid, and the quartile lines switch to dashed. Here's how to do it step by step:

1. First, Make Sure You Have the Split Violin Function

First, let's include the full GeomSplitViolin definition from @jan-glx (since you mentioned using it):

# Define the split violin geom from @jan-glx
GeomSplitViolin <- ggproto("GeomSplitViolin", GeomViolin, 
                          draw_group = function(self, data, ..., draw_quantiles = NULL) {
  data <- transform(data, xminv = x - violinwidth * (x - xmin), xmaxv = x + violinwidth * (xmax - x))
  grp <- data[1, "group"]
  newdata <- plyr::arrange(transform(data, x = if (grp %% 2 == 1) xminv else xmaxv), if (grp %% 2 == 1) y else -y)
  newdata <- rbind(newdata[1, ], newdata, newdata[nrow(newdata), ], newdata[1, ])
  newdata[c(1, nrow(newdata) - 1, nrow(newdata)), "x"] <- round(newdata[1, "x"])
  if (length(draw_quantiles) > 0 & !scales::zero_range(range(data$y))) {
    stopifnot(all(draw_quantiles >= 0), all(draw_quantiles <= 1))
    quantiles <- ggplot2:::create_quantile_segment_frame(data, draw_quantiles)
    aesthetics <- data[rep(1, nrow(quantiles)), setdiff(names(data), c("x", "y")), drop = FALSE]
    aesthetics$alpha <- rep(1, nrow(quantiles))
    both <- cbind(quantiles, aesthetics)
    quantile_grob <- GeomPath$draw_panel(both, ...)
    ggplot2:::ggname("geom_split_violin", grid::grobTree(GeomPolygon$draw_panel(newdata, ...), quantile_grob))
  } else {
    ggplot2:::ggname("geom_split_violin", GeomPolygon$draw_panel(newdata, ...))
  }
})

geom_split_violin <- function(mapping = NULL, data = NULL, stat = "ydensity", position = "identity", ..., 
                              draw_quantiles = NULL, trim = TRUE, scale = "area", na.rm = FALSE, 
                              show.legend = NA, inherit.aes = TRUE) {
  layer(data = data, mapping = mapping, stat = stat, geom = GeomSplitViolin, 
        position = position, show.legend = show.legend, inherit.aes = inherit.aes, 
        params = list(trim = trim, scale = scale, draw_quantiles = draw_quantiles, na.rm = na.rm, ...))
}

2. Plot with Custom Line Styles

The key issue is that the draw_quantiles parameter in the split violin function applies the same line style to all quantiles. Instead, we'll use stat_summary separately to add the mean (solid) and quartiles (dashed) with distinct styles:

library(ggplot2)
library(plyr) # Required for the split violin function's arrange step

# Create the plot with iris dataset
ggplot(iris, aes(x = Species, y = Sepal.Length, fill = Species)) +
  # Draw split violin (no draw_quantiles here)
  geom_split_violin(trim = FALSE) +
  # Add solid mean line
  stat_summary(fun = mean, geom = "crossbar", width = 0.2, 
               color = "black", linetype = 1, size = 0.5) +
  # Add dashed 25th quartile line
  stat_summary(fun = quantile, fun.args = list(probs = 0.25), 
               geom = "crossbar", width = 0.2, color = "black", linetype = 2, size = 0.5) +
  # Add dashed 75th quartile line
  stat_summary(fun = quantile, fun.args = list(probs = 0.75), 
               geom = "crossbar", width = 0.2, color = "black", linetype = 2, size = 0.5) +
  theme_minimal() +
  labs(title = "Split Violin Plot: Solid Mean, Dashed Quartiles",
       y = "Sepal Length", x = "Iris Species")

3. Alternative: Use draw_quantiles for Quartiles + Separate Mean

If you prefer to use the draw_quantiles parameter for quartiles, you can set those to dashed first, then overlay a solid mean line:

ggplot(iris, aes(x = Species, y = Sepal.Length, fill = Species)) +
  geom_split_violin(trim = FALSE, draw_quantiles = c(0.25, 0.75), linetype = 2) +
  stat_summary(fun = mean, geom = "crossbar", width = 0.2, 
               color = "black", linetype = 1, size = 0.5) +
  theme_minimal()

This works because the mean line is drawn on top of the violin and quartile lines, ensuring it's visible as a solid line.


内容的提问来源于stack exchange,提问作者Y.Coch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:51:20