如何为ggplot2绘制的广义指数分布风险函数图添加图例
Great question! The problem here is that you’re manually adding each line with hard-coded colors outside of ggplot’s aesthetic mapping system—so ggplot doesn’t recognize these as distinct groups that need a legend. Let’s walk through two solid solutions, starting with the most scalable one.
1. Convert to Tidy Data (Recommended Approach)
ggplot is designed to work best with tidy data (one observation per row, one variable per column). Your current data frame is in "wide" format, which makes it hard for ggplot to track groups. Here’s how to restructure it:
First, let’s clean up variable names to avoid confusion (your x-axis variable a clashes with the hazard function’s a parameter—let’s rename it x):
library(ggplot2) library(tidyr) library(dplyr) # Define the hazard function hazard <- function(x, a, b) { (a*b*exp(-b*x)*((1-exp(-b*x))^(a-1)))/(1-((1-exp(-b*x))^a)) } # Create x-axis values x_vals <- seq(1, 30, 1) # Create a data frame of parameter combinations with labels params <- tibble( group = c("a=0.2, b=0.5", "a=1, b=0.5", "a=0.5, b=1", "a=2, b=2"), a_param = c(0.2, 1, 0.5, 2), b_param = c(0.5, 0.5, 1, 2) ) # Expand to all x-value + parameter combinations, then calculate hazard df_tidy <- expand.grid(x = x_vals, group = params$group) %>% left_join(params, by = "group") %>% mutate(hazard_val = hazard(x, a_param, b_param)) # Plot with automatic legend ggplot(df_tidy, aes(x = x, y = hazard_val, colour = group)) + geom_line(linewidth = 1) + # Optional: make lines thicker for visibility ylab("Hazard Function") + ggtitle("Plotting the Hazard Function") + theme_minimal()
Why this works:
- We map the
groupvariable (which labels each parameter set) to thecolouraesthetic insideaes(). - ggplot automatically generates a legend matching each group label to its line color.
- This approach scales easily—add more parameter combinations to the
paramstibble, and the plot will update without extrageom_line()calls.
2. Quick Fix: Manual Color Mapping
If you want to keep your original wide data frame, you can manually map colors within the aesthetic system to trigger a legend:
library(ggplot2) hazard<-function(x,a,b) { h=(a*b*exp(-b*x)*((1-exp(-b*x))^(a-1)))/(1-((1-exp(-b*x))^a)) return(h) } a=seq(1,30,1) y1=hazard(a,0.2,0.5) y2=hazard(a,1,0.5) y3=hazard(a,0.5,1) y4=hazard(a,2,2) df=data.frame(a,y1,y2,y3,y4) ggplot(df,aes(a))+ geom_line(aes(y=y1, colour="a=0.2, b=0.5"))+ geom_line(aes(y=y2, colour="a=1, b=0.5"))+ geom_line(aes(y=y3, colour="a=0.5, b=1"))+ geom_line(aes(y=y4, colour="a=2, b=2"))+ # Manually set colors to match your original code scale_colour_manual(values = c("blue", "red", "green", "black")) + ylab("hazard function")+ ggtitle("Plotting the hazard function")
Why this works:
- By moving
colourinsideaes()and assigning a label string, we tell ggplot to treat each line as a separate group. scale_colour_manual()lets us keep your original color choices while linking them to the legend labels.
Both methods will add a proper legend to your plot—stick with the tidy data approach if you plan to expand the plot later!
内容的提问来源于stack exchange,提问作者Soham Bagchi

