2011-03-01 110 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