【问题标题】:Ensure minimum distance between adjacent points确保相邻点之间的最小距离
【发布时间】:2011-03-02 01:37:02
【问题描述】:

我有一个包含 15-25 个数据点的列表/框架。它们都在 0 到 100 之间,并且有一些簇(比如 72 左右)。显示此数据时,我想增加每对点之间的距离,使其至少为 2(例如 69.4 和 71.4 将是两个相邻点)。

但是,我需要确保我保持整体秩序,并使每个点都尽可能接近最初的位置。

我的积分清单很简单

scores <- c(13.343, 17.998, 25.413, 27.721, 33.361, 47.263, 52.298, 55.981,
            57.851, 72.038, 72.204, 72.296, 73.472, 75.925, 80.748, 85.998)

我想增加点簇之间的距离。 72.038 - 72.296 的点都将向下移动以确保更均匀的价差。

spacedScores <- c(13.343, 17.998, 25.413, 27.721, 33.361, 47.263, 52.298,
                  55.981, 57.851, 67.925, 69.925, 71.925, 73.925, 75.925,
                  80.748, 85.998)

关于如何在 R 中最干净地做到这一点的任何建议?

澄清:我不一定要寻找数学上的最佳解决方案,只是一些非常好的东西。我也经常想象一些点需要向上移动,一些点需要向下移动——这很好。

【问题讨论】:

    标签: r


    【解决方案1】:

    您可以使用diff(scores) 查找点之间的距离(我假设值已排序)。

    然后使用which(diff(scores) &lt; 2) 识别“坏点”并将它们向后移动,使间距 = 2。

    问题是,移动一个点来修正一个距离可能会使上一个或下一个距离变为

    这是一个我“蛮力”解决方案的示例。您可能需要引入一个计数器以避免无限循环

    scores <- c(13.343, 17.998, 25.413, 27.721, 33.361, 47.263,
        52.298, 55.981, 57.851, 72.038, 72.204, 72.296, 73.472, 
        75.925, 80.748, 85.998)
    spacedScores <- c(13.343, 17.998, 25.413, 27.721, 33.361, 
        47.263, 52.298, 55.981, 57.851, 67.925, 69.925, 71.925, 
        73.925, 75.925, 80.748, 85.998)
    
    plot(scores, pch=20)
    points(spacedScores, pch='x', col="red")
    
    badPoints <- which(diff(scores) < 2)
    
    while (length(badPoints) > 0)
      {
      scores[badPoints] <- scores[badPoints] - (2 - diff(scores)[badPoints])
      badPoints <- which(diff(scores) < 2)
      }
    
    points(scores, pch='o', col="green")
    

    结果如下:黑色是原始点,绿色是修改后的点,红色是您提供的间隔点

    【讨论】:

    • 太棒了,谢谢!我通过减去((2.1-diff)/2) 并将相同的值添加到上面的下一个值来稍微改变它以向上和向下推。本质上只是将彼此推开一半的距离,而不是仅仅移动一个整个距离。这太棒了,谢谢。我还必须使用 2.1 -...,那样它(不应该)陷入无法解决的循环中。
    【解决方案2】:

    我编写了一个 hackish bruteforce 方法,它迭代了几次,直到每个 diff 都大于 2,并且在数据集中需要最小的修改:

    scores <- c(13.343, 17.998, 25.413, 27.721, 33.361, 47.263, 52.298, 55.981, 57.851, 72.038, 72.204, 72.296, 73.472, 75.925, 80.748, 85.998)
    
    done <- 0
    while (any(diff(scores)<2)) {
    diffs <- diff(scores)
    closevals <- which(diffs < 2)
    first <- closevals[which.min(diffs[closevals])]
    if (which.min(diff(scores[(first-1):(first+1)])) == 1) {
        scores[1:(first-1)] <- scores[1:(first-1)] - (2 - (scores[first] - scores[first-1]))
        } else {
            scores[(first+1):length(scores)] <- scores[(first+1):length(scores)] + (2 - (scores[first+1] - scores[first]))
        }
    }
    > scores
     [1] 13.343 17.998 25.413 27.721 33.361 47.263 52.298 55.981 57.981 72.168
    [11] 74.168 76.168 78.168 80.621 85.444 90.694
    

    编辑:我刚刚看到给出了更好更简单的答案(结果完全相同)。我没有删除复杂答案的唯一原因是,我的循环还会检查是否将一个小数字添加到两个数字之间的差异中会更好,而不是总是从较小的值中减去 2-diff()

    我希望我的解决方案可以更好地用于真实数据:)

    【讨论】:

    • 谢谢,无论如何,+1 的好答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    • 2021-10-24
    • 2021-07-31
    • 2015-10-16
    • 1970-01-01
    • 1970-01-01
    • 2016-10-31
    相关资源
    最近更新 更多