You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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 (adjust x and hjust/vjust to 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:08:57