ggplot2如何自动为均值两侧连续出现5次的数值绘制包围矩形
实现方法
核心思路是先用游程编码(RLE)自动识别连续出现在均值同一侧的符合长度要求的序列,自动计算矩形坐标后传入ggplot的geom_rect图层即可,无需手动指定坐标。
第一步:数据预处理,自动生成矩形坐标数据
你可以结合基础R的rle游程编码函数快速筛选符合要求的连续序列,代码适配你提供的示例数据:
library(ggplot2) library(dplyr) # 你的原始示例数据 mydata <- data.frame( id = c(1:20), result = c(102,99,102,99,102, rep.int(105,5), 102,99,102,99,102, rep.int(95,5)) ) mymean <- 100 # 给数据打标签:判断每个点位于均值上方/下方 mydata <- mydata %>% mutate(side = case_when( result > mymean ~ "up", result < mymean ~ "down", TRUE ~ "equal" # 刚好等于均值的点不计入同侧序列 )) # 游程编码识别连续序列 rle_res <- rle(mydata$side) rect_df <- data.frame() current_pos <- 1 # 遍历所有连续段,筛选长度≥5的段,计算对应矩形坐标 for (i in seq_along(rle_res$lengths)) { seg_len <- rle_res$lengths[i] seg_side <- rle_res$values[i] if (seg_len >=5 && seg_side %in% c("up", "down")) { # x轴左右各留0.5边距,刚好完整包围整段的点 xmin <- current_pos - 0.5 xmax <- current_pos + seg_len - 0.5 # 提取该段的数值计算y轴范围 seg_data <- mydata[current_pos:(current_pos+seg_len-1), ] ymin <- ifelse(seg_side == "up", mymean, min(seg_data$result)-1) ymax <- ifelse(seg_side == "up", max(seg_data$result)+1, mymean) rect_df <- rbind(rect_df, data.frame(xmin, xmax, ymin, ymax)) } current_pos <- current_pos + seg_len }
第二步:绘图时添加矩形图层
只需在原有绘图代码的基础上,新增geom_rect图层传入刚才自动生成的矩形坐标数据即可:
ggplot(mydata, aes(x = id, y = result)) + geom_point(size = 2) + geom_hline(yintercept = mymean, linewidth = 1) + # 加入自动生成的包围框,设置透明度避免遮盖数据点 geom_rect(data = rect_df, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax), inherit.aes = FALSE, fill = "gold", alpha = 0.3, color = "gray30")
你可以根据需求自行调整矩形的填充色、透明度、边框样式等参数。
内容的提问来源于stack exchange,提问作者reidj
相关产品推荐
相关产品推荐

