如何在ggplot2环形图上添加概率水平环形轴
Adding Circular Probability Axes to Polar Bar Chart
Got it, let's sort out how to add those circular probability rings (0.25, 0.75, 1, etc.) to your donut chart. The key here is remembering that in coord_polar(), the y-axis values correspond directly to the radius of the circles—so we can leverage geom_hline() to create the rings, and adjust our annotations to sit correctly on them.
Here's the modified code with explanations:
library(tidyverse) library(ggplot2) # Load your data (using the provided structure for reproducibility) data <- structure(list(id = 1:6, individual = structure(c(1L, 12L, 23L, 26L, 27L, 28L), .Label = c("Person 1", "Person 10", "Person 11", "Person 12", "Person 13", "Person 14", "Person 15", "Person 16", "Person 17", "Person 18", "Person 19", "Person 2", "Person 20", "Person 21", "Person 22", "Person 23", "Person 24", "Person 25", "Person 26", "Person 27", "Person 28", "Person 29", "Person 3", "Person 30", "Person 31", "Person 4", "Person 5", "Person 6", "Person 7", "Person 8", "Person 9"), class = "factor"), value = c(0.658333333, 0.958333333, 0.720833334, 0.883333333, 0.779166667, 0.9375), group = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = "A", class = "factor")), .Names = c("id", "individual", "value", "group"), row.names = c(NA, 6L), class = "data.frame") label_data <- structure(list(id = 1:6, individual = structure(c(1L, 12L, 23L, 26L, 27L, 28L), .Label = c("Person 1", "Person 10", "Person 11", "Person 12", "Person 13", "Person 14", "Person 15", "Person 16", "Person 17", "Person 18", "Person 19", "Person 2", "Person 20", "Person 21", "Person 22", "Person 23", "Person 24", "Person 25", "Person 26", "Person 27", "Person 28", "Person 29", "Person 3", "Person 30", "Person 31", "Person 4", "Person 5", "Person 6", "Person 7", "Person 8", "Person 9"), class = "factor"), value = c(0.658333333, 0.958333333, 0.720833334, 0.883333333, 0.779166667, 0.9375), group = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = "A", class = "factor"), hjust = c(0, 0, 0, 0, 0, 0), angle = c(84.375, 73.125, 61.875, 50.625, 39.375, 28.125)), .Names = c("id", "individual", "value", "group", "hjust", "angle"), row.names = c(NA, 6L), class = "data.frame") # Your original data prep steps empty_bar <- 1 to_add <- data.frame(matrix(NA, empty_bar*nlevels(data$group), ncol(data))) colnames(to_add) <- colnames(data) to_add$group <- rep(levels(data$group), each=empty_bar) data <- rbind(data, to_add) %>% arrange(group) data$id <- seq(1, nrow(data)) number_of_bar <- nrow(label_data) angle <- 90 - 360 * (label_data$id-0.5) /32 label_data$hjust <- ifelse( angle < -90, 1, 0) label_data$angle <- ifelse(angle < -90, angle+180, angle) # Create a data frame for our probability rings and labels prob_levels <- c(0, 0.25, 0.5, 0.75, 1) ring_data <- data.frame(y = prob_levels) label_positions <- data.frame(y = prob_levels, x = 1) # x can be any id since it's polar p <- ggplot(data, aes(x=as.factor(id), y=value)) + # Add the circular rings first (so they sit behind the bars) geom_hline(data = ring_data, aes(yintercept = y), color = "grey", linetype = "dashed", alpha = 0.7) + # Your original bar layer geom_bar(stat="identity", fill=alpha("skyblue", 0.7)) + ylim(-0.3,1) + theme_minimal() + theme( axis.text = element_blank(), axis.title = element_blank(), panel.grid = element_blank(), plot.margin = unit(rep(-1,4), "cm") ) + coord_polar(start = 0) + # Your original person labels geom_text(data=label_data, aes(x=id, y=value, label=individual, hjust=hjust), color="black", fontface="bold", alpha=0.6, size=2.5, angle= label_data$angle, inherit.aes = FALSE ) + # Add probability labels to the rings geom_text(data = label_positions, aes(x = x, y = y, label = paste0("p=", y)), color = "black", size = 3, hjust = 1, vjust = -0.5) + # Optional: keep the center p=0 label if needed (though it's now in the ring labels) annotate("text", label = "p=0", x = 0, y = 0, color = "black", size = 3) p
Key Changes Explained:
geom_hline()for Circular Rings: In polar coordinates, a horizontal line (y = constant) is rendered as a circle with radius equal to that constant value. Perfect for our probability axes!- Ring Label Data Frame: We create a small data frame to hold our probability levels, then use
geom_text()to place the labels on the left side of each ring (adjustxandhjust/vjustto move them if needed). - Layer Order: We add the rings first so they appear behind the bars, keeping the chart readable.
If you want thicker rings or different linetypes, just adjust the size and linetype arguments in geom_hline().
内容的提问来源于stack exchange,提问作者Marek
相关产品推荐
相关产品推荐

