使用ggplot2的geom_density绘制组内密度及组密度估计加权平均密度
Got it, let's walk through how to create exactly the plot you're asking for—group density curves plus a weighted average of those group-level density estimates (not the density of all combined data points). Here's a step-by-step implementation using tidyverse tools for clarity and flexibility:
Step 1: Load Packages and Generate Data
First, we'll load the tidyverse suite (for data manipulation and plotting) and generate your sample data with a seed set to ensure reproducibility:
library(tidyverse) # Set seed for reproducible results set.seed(123) # Generate your data x = c(rnorm(mean=0.0, n=100), rnorm(mean=1.0, n=100), rnorm(mean=2.0, n=200)) g = c(rep('a', 100), rep('b', 100), rep('c', 200)) d = data.frame(x=x, g=as.factor(g))
Step 2: Calculate Group Densities on a Unified Grid
To compute a meaningful average of density estimates, we first need to ensure all groups' densities are calculated over the same x-axis range and grid points. This way, we can align density values at identical x positions:
# Get the full range of x values across all groups x_range = range(d$x) # Create a unified grid of 1000 x points (adjustable) x_grid = seq(x_range[1], x_range[2], length.out = 1000) # Calculate density for each group and map to the unified grid group_densities = d %>% group_by(g) %>% summarise( # Compute density for the group, spanning the full x range dens = list(density(x, from = x_range[1], to = x_range[2])), # Store group sample size for weighting n = n(), .groups = "drop" ) %>% # Interpolate density values to match our unified x grid mutate(dens_values = map(dens, ~ approx(.x$x, .x$y, xout = x_grid)$y)) %>% # Unnest into a long-format data frame for plotting unnest(cols = dens_values) %>% mutate(x = rep(x_grid, nrow(.)/length(x_grid)))
Step 3: Compute Weighted Average Density
We'll calculate the weighted average using group sample sizes as weights (since group c has twice as many observations as a or b). If you want an unweighted average instead, just replace n / total_n with 1 / n_distinct(g):
# Total number of observations total_n = nrow(d) # Calculate weighted average density at each x grid point average_density = group_densities %>% group_by(x) %>% summarise( weighted_avg_dens = sum(dens_values * (n / total_n)), .groups = "drop" )
Step 4: Plot the Results
Finally, we'll use ggplot2 to layer the group density curves and the weighted average curve, styling it to match typical publication-ready plots:
ggplot() + # Plot group density curves (semi-transparent for clarity) geom_line( data = group_densities, aes(x = x, y = dens_values, color = g), alpha = 0.5, linewidth = 1 ) + # Plot weighted average density (bold black dashed line) geom_line( data = average_density, aes(x = x, y = weighted_avg_dens), color = "black", linewidth = 1.2, linetype = "dashed" ) + # Add labels and title labs( x = "x", y = "Density", color = "Group", title = "Group Densities with Weighted Average of Density Estimates" ) + # Clean up the theme theme_minimal() + theme( plot.title = element_text(hjust = 0.5, size = 14, face = "bold"), legend.position = "top" )
Key Notes:
- The unified x grid ensures we're averaging density values at the exact same x positions, which is critical for a valid average of density estimates.
- You can tweak the plot styling (colors, line types, transparency) to match your target example—just adjust the arguments in
geom_line()andtheme(). - For an unweighted average, swap the weighting term in
average_densityto1 / n_distinct(g)(which would be 1/3 for your 3 groups).
内容的提问来源于stack exchange,提问作者adn bps

