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

如何在R中垂直分布矩形以避免重叠(保持x坐标不变)

垂直重排矩形消除重叠(固定x坐标)

我有一组存储在R数据框中的矩形,每个矩形由xmin、ymin、xmax、ymax坐标表示,部分矩形存在重叠。需要将这些矩形绘制在图表上,仅通过垂直移动重新分布,确保任意两个矩形不重叠,同时保留矩形的x坐标不变。

原始重叠矩形示例代码

df <- structure(list(xmin = c(67.705914, 6.005184, 66.162244, 87.99481, 
46.082243, 16.280928, 47, 3.4155154, 23.347187, 84.895525, 82.80274, 
16.85878, 4.3557265, 6.625263, 7.626907, 96.220383, 12.115471, 
30.235073, 46.082243, 16.280928, 79.90225, 29.42548, 84.895525, 
23.347184, 3.198581, 7.2832146, 25.539455, 1.695044, 34.425616, 
3.87074, 78.284034, 89.64427, 87.0506, 87.68941, 75.329986, 2.213225, 
3.4155154, 4.6098725, 0.5424367, 80.416396, 12.115471, 6.625263, 
32.722494, 8.344733, 89.64427, 52.48499, 90.12926, 30.235073, 
2.9885126, 8.719267), xmax = c(73.705914, 12.005184, 72.162244, 
93.99481, 52.082243, 22.280928, 53, 9.4155154, 29.347187, 90.895525, 
88.80274, 22.85878, 10.3557265, 12.625263, 13.626907, 102.220383, 
18.115471, 36.235073, 52.082243, 22.280928, 85.90225, 35.42548, 
90.895525, 29.347184, 9.198581, 13.2832146, 31.539455, 7.695044, 
40.425616, 9.87074, 84.284034, 95.64427, 93.0506, 93.68941, 81.329986, 
8.213225, 9.4155154, 10.6098725, 6.5424367, 86.416396, 18.115471, 
12.625263, 38.722494, 14.344733, 95.64427, 58.48499, 96.12926, 
36.235073, 8.9885126, 14.719267), ymin = c(15.6854458039728, 
29.280227138751, 85.6077652217337, 11.1447959143222, 88.6507847970509, 
47.8780668201714, 58.249961106352, 20.7963843697899, 39.1374442773956, 
14.253314246173, 31.2038928836167, 75.406238562994, 90.8407922528565, 
34.3969058783788, 90.0758115822633, 47.8810408921933, 41.9826622904241, 
18.4008825788269, 64.0816967514961, 26.1344753018713, 87.6969580943045, 
29.8031653049004, 25.5889076966207, 24.8832114234653, 65.6939979329678, 
83.7251558885676, 62.3262453418105, 52.1180170583712, 22.2274072090833, 
46.6403205808079, 51.4982774017124, 52.9611597344073, 86.5149513741532, 
8.71673006759099, 73.63580649852, 10.2390589604505, 79.6728413001311, 
27.0399934909858, 17.2084996917785, 28.7198728007395, 27.7845507714287, 
64.8898031132345, 77.518346688506, 11.785758214691, 51.2219947101639, 
55.4683310942946, 59.4959604756725, 15.6990628891733, 53.6174786549635, 
49.4079504426206), ymax = c(17.2907089618675, 31.2234089569328, 
87.3295043521685, 13.2730010425273, 90.8437672531913, 50.9203203412982, 
60.4271762962254, 23.1819265384646, 41.6096664996178, 15.6887703563279, 
34.0475653401924, 77.3496347894091, 93.4576597227361, 37.1520079191952, 
92.2237107419272, 52.1189591078067, 43.7265046549561, 21.6912051594721, 
65.7843994541988, 28.3922072606342, 89.9154454892625, 33.7570368040767, 
27.4828470905601, 26.6122436815298, 69.5273312663012, 86.1164074074011, 
64.1048569740807, 55.1107177882982, 23.6523109318047, 48.9688920093793, 
54.4445139608521, 55.219401492649, 88.3781992374011, 11.2337368703121, 
75.7899915205464, 13.1508236663329, 85.2391063603721, 29.4730210139216, 
20.1518959181936, 33.1198728007395, 30.7228223763669, 66.81402503475, 
79.1315542356758, 13.8413137702466, 52.7337440574224, 57.6201635550276, 
61.8678354756725, 19.1313772996537, 55.6110888786056, 51.560255051839
)), row.names = c(NA, -50L), class = "data.frame")

ggplot(df,aes(xmin=xmin,xmax=xmax,ymin=ymin,ymax=ymax)) + geom_rect(color="black",fill="cyan") + theme_void()

运行上述代码会得到存在重叠的矩形图表。

尝试过的方法

  • 查阅资料未找到R语言中仅垂直移动消除矩形重叠的现成方案
  • 尝试使用beeswarm包的swarmy函数随机移动矩形,但矩形数量较多时效率极低

最终解决方案代码

通过自定义重叠检测函数,逐个调整矩形的垂直位置,确保无重叠:

library(ggplot2)

#' 检测单个矩形是否与矩形集合中的任意矩形重叠
#'
#' @param testRect 待检测的矩形(需包含xmin、xmax、ymin、ymax属性)
#' @param rectList 矩形集合数据框,需包含xmin、xmax、ymin、ymax列
#' @returns 布尔值:TRUE表示存在重叠,FALSE表示无重叠
#' 
overlaps_any <- function(testRect, rectList) {
  if(nrow(rectList)==0) {
    return(FALSE)
  }
  for (r in 1:nrow(rectList)) {
    # 面积为0的矩形不参与重叠检测
    if (testRect$xmin == testRect$xmax || testRect$ymax == testRect$ymin || rectList[r,"xmin"] == rectList[r,"xmax"] || rectList[r,"ymax"] == rectList[r,"ymin"]) {
      next
    }
    
    # 水平方向无重叠则跳过
    if (testRect$xmin > rectList[r,"xmax"] || rectList[r,"xmin"] > testRect$xmax) {
      next
    }
    
    # 垂直方向无重叠则跳过
    if (testRect$ymin > rectList[r,"ymax"] || rectList[r,"ymin"] > testRect$ymax) {
      next
    }
    return(TRUE)
  }
  return(FALSE)
}

# 创建空数据框存储调整后的矩形
df.new <- data.frame()

# 逐个处理原始数据框中的矩形
for(r in 1:nrow(df)) {
  # 取出当前矩形
  testRect <- df[r,]
  
  # 保留矩形高度
  rect_height <- testRect$ymax - testRect$ymin
  
  # 初始位置设为y轴底部
  testRect$ymin <- 0
  testRect$ymax <- testRect$ymin + rect_height
  
  # 循环调整垂直位置直到无重叠
  while(overlaps_any(testRect, df.new)) {
    testRect$ymin <- testRect$ymin + 1
    testRect$ymax <- testRect$ymax + 1
  }
  
  # 将调整后的矩形加入新数据框
  df.new <- rbind(df.new, testRect)
}

# 绘制无重叠的矩形图表
print(
  ggplot(df.new, aes(
    xmin = xmin,
    xmax = xmax,
    ymin = ymin,
    ymax = ymax
  )) +
    geom_rect(color = "black", fill = "cyan") + coord_fixed() + theme_void()
)

运行该代码后可得到无重叠的垂直分布矩形图表。


内容的提问来源于stack exchange,提问作者kurpav00

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:27:00