R绘图添加图例问题:含核密度、正态密度与直方图
Fixing Legend Display for Iris Histograms with Density Curves
Hey there! The reason your legends aren't showing up is that you're using coordinates (1, 95) that fall way outside the bounds of your plots. Since you set freq=FALSE in hist(), the y-axis represents density values (not raw counts), which for the iris sepal length data only go up to around 1.0—so 95 is way off the chart!
Quick Fix for Your Existing Code
Simply replace the hardcoded coordinates in legend() with a keyword position that automatically fits within the plot, like "topright", "topleft", or "bottomright". Here's your adjusted code:
# Setosa plot setosa_length <- iris$Sepal.Length[iris$Species == "setosa"] hist(setosa_length, freq=FALSE, main="Setosa Sepal Length") x <- seq(4, 8, length.out=100) y <- dnorm(x, mean(setosa_length), sd(setosa_length)) lines(x, y, col="red") lines(density(setosa_length), col="blue") # Use keyword position instead of hardcoded coordinates legend("topright", legend=c("Normal Density", "Kernel Density"), col=c("red", "blue"), lty=1, cex=0.8) # Versicolor plot versicolor_length <- iris$Sepal.Length[iris$Species == "versicolor"] hist(versicolor_length, freq=FALSE, main="Versicolor Sepal Length") x <- seq(4, 8, length.out=100) y <- dnorm(x, mean(versicolor_length), sd(versicolor_length)) lines(x, y, col="red") lines(density(versicolor_length), col="blue") legend("topright", legend=c("Normal Density", "Kernel Density"), col=c("red", "blue"), lty=1, cex=0.8) # Virginica plot virginica_length <- iris$Sepal.Length[iris$Species == "virginica"] hist(virginica_length, freq=FALSE, main="Virginica Sepal Length") x <- seq(4, 8, length.out=100) y <- dnorm(x, mean(virginica_length), sd(virginica_length)) lines(x, y, col="red") lines(density(virginica_length), col="blue") legend("topright", legend=c("Normal Density", "Kernel Density"), col=c("red", "blue"), lty=1, cex=0.8)
Bonus: Clean Up Your Code with a Loop
Since you're repeating the same code three times, using a loop will make your script shorter and easier to maintain:
# Get unique species names species_list <- unique(iris$Species) # Loop through each species for(species in species_list) { # Extract sepal length data length_data <- iris$Sepal.Length[iris$Species == species] # Create histogram with density hist(length_data, freq=FALSE, main=paste(species, "Sepal Length"), xlab="Sepal Length", ylab="Density") # Generate x values for normal curve x <- seq(min(iris$Sepal.Length), max(iris$Sepal.Length), length.out=100) # Calculate normal density y_norm <- dnorm(x, mean(length_data), sd(length_data)) # Add normal curve lines(x, y_norm, col="red") # Add kernel density curve lines(density(length_data), col="blue") # Add legend in top-right corner legend("topright", legend=c("Normal Density", "Kernel Density"), col=c("red", "blue"), lty=1, cex=0.8) }
Key Notes:
- Using keyword positions like
"topright"ensures the legend stays within the plot area automatically, no need to guess coordinates. - I removed the
with(iris, ...)since you're already working with a subset of the data—it's not necessary here. - The loop version uses
unique(iris$Species)to dynamically get all species, so if you add more data later, it will still work.
内容的提问来源于stack exchange,提问作者Shilpa Kancharla
相关产品推荐
相关产品推荐

