R语言ggplot2自定义图例需求:为不同中心节点设置区分色图例
Fixing Legend Colors for Mahalanobis & MCD Centers in ggplot2
Hey there! I totally get where you're coming from—ggplot2's legend system can feel way more convoluted than what you might be used to in Python when you're just starting out with R. Let's get your centers showing up in the legend with different colors properly.
What Was Off in Your Original Code
- You hardcoded colors (
color = "blue"/color = "red") directly ingeom_pointinstead of mapping them throughaes(), so ggplot didn't link those points to the legend. - Default point shapes (like shape 19) don't support fill colors, so using
fill=in your aes wasn't doing anything visible. - The ellipses and points weren't sharing a unified legend mapping, leading to inconsistent or missing legend entries.
Revised Code
library(ggplot2) library(MASS) library(car) library(robustbase) data("airquality") # Select only Ozone and Temp variables air = airquality[c("Ozone" , "Temp")] air = na.omit(air) # Mahalanobis calculations air.center = colMeans(air) air.cov = cov(air) rad = sqrt(qchisq(p = 0.95 , df = ncol(air))) ellipse <- as.data.frame(ellipse(center = air.center , shape = air.cov , radius = rad , segments = 150 , draw = FALSE)) colnames(ellipse) <- colnames(air) distances <- mahalanobis(x = air , center = air.center , cov = air.cov) cutoff <- qchisq(p = 0.95 , df = ncol(air)) # MCD calculations Y_mcd <- covMcd(air) ellipse_mcd <- data.frame(ellipse(center = Y_mcd$center, shape = Y_mcd$cov, radius= rad, segments=100,draw=FALSE)) colnames(ellipse_mcd) <- colnames(air) # Modified plot code plot_fig <- ggplot(air , aes(x = Ozone , y = Temp)) + # Base scatter points geom_point(size = 2) + # Mahalanobis ellipse: map fill/color to a label, disable inherited aes to avoid conflicts geom_polygon(data = ellipse, aes(fill = "Mahalanobis", color = "Mahalanobis"), alpha = 0.5, inherit.aes = FALSE) + # Mahalanobis center: use shape 21 (supports fill) and map to label geom_point(aes(x = air.center[1], y = air.center[2], fill = "Mahalanobis", color = "Mahalanobis"), size = 5, shape = 21) + # Label outliers geom_text(data=subset(air, distances > cutoff), aes(Ozone,Temp,label=row.names(air[distances > cutoff ,])), hjust = 1 , vjust = -1.5 ,size = 3.5)+ # Axis labels and title ylab("Temperature Values") + xlab("Ozone Values") + ggtitle("Mahalanobis Distance vs. MCD") + # MCD ellipse: map fill/color to label geom_polygon(data=ellipse_mcd,aes(fill = "MCD", color = "MCD"), alpha=0.3, inherit.aes = FALSE) + # MCD center: shape 21 for fill mapping geom_point(aes(x = Y_mcd$center[1], y = Y_mcd$center[2], fill = "MCD", color = "MCD"), size = 6, shape = 21) + # Manual scales to set colors and unify legend scale_fill_manual(name = "Method", values = c("Mahalanobis" = "blue", "MCD" = "red")) + scale_color_manual(name = "Method", values = c("Mahalanobis" = "blue", "MCD" = "red")) + # Legend position adjustment theme( legend.position = c(0.95, 0.15), legend.justification = c("right", "top") ) plot_fig
Key Changes Explained
- Shape Selection: We use
shape = 21for the center points—this is a circle with a separate fill (inner color) and color (border color), which lets the legend properly display the point style. - Aesthetic Mapping: All elements (ellipses and centers) have their
fillandcolormapped to a label ("Mahalanobis" or "MCD") insideaes(), instead of hardcoding colors. This tells ggplot to create legend entries for these labels. - Unified Legend: We use
scale_fill_manualandscale_color_manualwith the same legend name ("Method") and color values. This merges the ellipse and point entries into a single, clean legend. inherit.aes = FALSE: Added togeom_polygonto prevent inheriting unnecessary aesthetic mappings from the main ggplot call, avoiding conflicts.
内容的提问来源于stack exchange,提问作者entryscience
相关产品推荐
相关产品推荐

