2011-03-01 65 views
4

我有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中最干净地做到这一点的任何建议?

澄清:我不一定要找一个数学上最优的解决方案,只是一些很不错。我大多数时候也会想到有些观点需要向上移动,有些观点则会降低 - 这很好。

回答

4

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

然后使用which(diff(scores) < 2)以鉴定“坏点”,并将它们向后移动,以使间距= 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") 

这里的结果:在黑色原始分,在绿色的修改点,在红色您提供的间隔点

example plot

+0

太棒了,谢谢!我稍微改变它,通过减去'((2.1-diff)/ 2)'并且将相同的值加到上面的下一个值来上下推动。基本上只是把原来的一半推向彼此,而不是把整个距离移动一次。这太棒了,谢谢。我也不得不使用2.1 -...,这样它(不应该)陷入它无法解决的循环中。 – chmullig 2011-03-01 17:46:54

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()

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

+0

谢谢,无论如何,这个好的答案+1。 – chmullig 2011-03-01 17:44:37