如何用R绘制可读分组环形图?解决现有绘图不可辨识问题
优化分组环形图可读性的求助
我用R代码制作分组环形图,但生成的图表完全无法辨识,数据为多分组带数值的结构,代码如下:
# library library(tidyverse) # load your data (from files) data <- read.csv("C:/Users/HP/Downloads/data.csv") # 'empty bar' to add at the end of each group empty_bar <- 3 to_add <- data.frame( matrix(NA, empty_bar*nlevels(data$topic), ncol(data)) ) colnames(to_add) <- colnames(data) to_add$topic <- rep(levels(data$topic), each=empty_bar) data <- rbind(data, to_add) data <- data %>% arrange(topic) data$id <- seq(1, nrow(data)) # name and the y position of each label label_data <- data number_of_bar <- nrow(label_data) angle <- 90 - 360 * (label_data$id-0.5) /number_of_bar # I substract 0.5 because the letter must have the angle of the center of the bars. Not extreme right(1) or extreme left (0) label_data$hjust <- ifelse( angle < -90, 1, 0) label_data$angle <- ifelse(angle < -90, angle+180, angle) # prepare a data frame for base lines base_data <- data %>% group_by(topic) %>% summarize(start=min(id), end=max(id) - empty_bar) %>% rowwise() %>% mutate(title=mean(c(start, end))) # prepare a data frame for grid (scales) grid_data <- base_data grid_data$end <- grid_data$end[ c( nrow(grid_data), 1:nrow(grid_data)-1)] + 1 grid_data$start <- grid_data$start - 1 grid_data <- grid_data[-1,] # Make the plot p <- ggplot(data, aes(x=as.factor(id), y=value, fill=topic)) + geom_bar(aes(x=as.factor(id), y=value, fill=topic), stat="identity", alpha=0.5) + # Add a val=100/75/50/25 lines. I do it at the beginning to make sur barplots are OVER it. geom_segment(data=grid_data, aes(x = end, y = 80, xend = start, yend = 80), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) + geom_segment(data=grid_data, aes(x = end, y = 60, xend = start, yend = 60), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) + geom_segment(data=grid_data, aes(x = end, y = 40, xend = start, yend = 40), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) + geom_segment(data=grid_data, aes(x = end, y = 20, xend = start, yend = 20), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) + # Add text showing the value of each 100/75/50/25 lines annotate("text", x = rep(max(data$id),4), y = c(20, 40, 60, 80), label = c("20", "40", "60", "80") , color="grey", size=3 , angle=0, fontface="bold", hjust=1) + geom_bar(aes(x=as.factor(id), y=value, fill=topic), stat="identity", alpha=4) + ylim(-300,70000) + theme_minimal() + theme( legend.position = "none", axis.text = element_blank(), axis.title = element_blank(), panel.grid = element_blank(), plot.margin = unit(rep(-0.1, 5), "cm")) + coord_polar() + geom_text(data=label_data, aes(x=id, y=value+10, label=tag, hjust=hjust), color="black", fontface="bold",alpha=0.6, size=2.5, angle= label_data$angle, inherit.aes = FALSE ) + # Add base line information geom_segment(data=base_data, aes(x = start, y = -5, xend = end, yend = -5), colour = "black", alpha=0.8, size=0.6 , inherit.aes = FALSE ) + geom_text(data=base_data, aes(x = title, y = -18, label=topic), hjust=c(1,1,1,0,0), colour = "black", alpha=0.8, size=4, fontface="bold", inherit.aes = FALSE) p
生成的图表存在元素重叠、刻度与数据量级不匹配等问题,完全不可读,恳请提供优化方案。
优化方案
1. 匹配刻度与数据量级
原代码刻度仅设置到80,但数据value值最高达数万,导致所有条形被拉伸重叠。根据数据范围重新设置刻度:
# 计算数据最大值,生成合理刻度 max_val <- max(data$value, na.rm = TRUE) tick_vals <- seq(0, max_val, by = 10000) # 生成刻度线段数据 grid_data <- base_data %>% rowwise() %>% mutate(ticks = list(tick_vals)) %>% unnest(ticks) # 替换原刻度线段和标注代码 geom_segment(data=grid_data, aes(x = end, y = ticks, xend = start, yend = ticks), colour = "grey", alpha=0.7, size=0.3 , inherit.aes = FALSE ) + annotate("text", x = rep(max(data$id), length(tick_vals)), y = tick_vals, label = as.character(tick_vals), color="grey", size=3 , angle=0, fontface="bold", hjust=1)
2. 移除重复绘图元素
代码重复调用geom_bar,保留一次即可避免图层重叠:
# 仅保留一次条形图绘制 geom_bar(stat="identity", alpha=0.8) +
3. 优化标签显示
- 过滤空行标签(添加的
empty_bar行无有效tag值):
label_data <- data %>% filter(!is.na(tag))
- 动态调整标签偏移量,避免与条形重叠:
geom_text(data=label_data, aes(x=id, y=value + max_val*0.02, label=tag, hjust=hjust), color="black", fontface="bold", alpha=0.8, size=2.5, angle= label_data$angle, inherit.aes = FALSE )
4. 调整分组间距
若分组过多,减少empty_bar数量避免环形图过于松散:
empty_bar <- 1
完整优化后代码示例
library(tidyverse) # 加载数据 data <- read.csv("C:/Users/HP/Downloads/data.csv") # 调整分组空行数量 empty_bar <- 1 to_add <- data.frame( matrix(NA, empty_bar*nlevels(data$topic), ncol(data)) ) colnames(to_add) <- colnames(data) to_add$topic <- rep(levels(data$topic), each=empty_bar) data <- rbind(data, to_add) data <- data %>% arrange(topic) data$id <- seq(1, nrow(data)) # 准备标签数据,过滤空值 label_data <- data %>% filter(!is.na(tag)) number_of_bar <- nrow(label_data) angle <- 90 - 360 * (label_data$id-0.5) /number_of_bar label_data$hjust <- ifelse( angle < -90, 1, 0) label_data$angle <- ifelse(angle < -90, angle+180, angle) # 基线数据 base_data <- data %>% group_by(topic) %>% summarize(start=min(id), end=max(id) - empty_bar) %>% rowwise() %>% mutate(title=mean(c(start, end))) # 刻度数据 max_val <- max(data$value, na.rm = TRUE) tick_vals <- seq(0, max_val, by = 10000) grid_data <- base_data %>% rowwise() %>% mutate(ticks = list(tick_vals)) %>% unnest(ticks) # 绘图 p <- ggplot(data, aes(x=as.factor(id), y=value, fill=topic)) + # 刻度线 geom_segment(data=grid_data, aes(x = end, y = ticks, xend = start, yend = ticks), colour = "grey", alpha=0.7, size=0.3 , inherit.aes = FALSE ) + # 刻度标注 annotate("text", x = rep(max(data$id), length(tick_vals)), y = tick_vals, label = as.character(tick_vals), color="grey", size=3 , angle=0, fontface="bold", hjust=1) + # 条形图 geom_bar(stat="identity", alpha=0.8) + # y轴范围 ylim(-max_val*0.1, max_val*1.1) + theme_minimal() + theme( legend.position = "bottom", axis.text = element_blank(), axis.title = element_blank(), panel.grid = element_blank(), plot.margin = unit(c(0.5,0.5,0.5,0.5), "cm")) + coord_polar() + # 标签 geom_text(data=label_data, aes(x=id, y=value + max_val*0.02, label=tag, hjust=hjust), color="black", fontface="bold", alpha=0.8, size=2.5, angle= label_data$angle, inherit.aes = FALSE ) + # 基线与分组标题 geom_segment(data=base_data, aes(x = start, y = -max_val*0.05, xend = end, yend = -max_val*0.05), colour = "black", alpha=0.8, size=0.6 , inherit.aes = FALSE ) + geom_text(data=base_data, aes(x = title, y = -max_val*0.08, label=topic), hjust=ifelse(angle < -90, 1, 0), colour = "black", alpha=0.8, size=4, fontface="bold", inherit.aes = FALSE) p
内容的提问来源于stack exchange,提问作者tores
相关产品推荐
相关产品推荐

