This repository has been archived by the owner on Nov 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
geomMed.py
52 lines (39 loc) · 1.78 KB
/
geomMed.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import math
def candMedian(dataPoints):
#Calculate the first candidate median as the geometric mean
tempX = 0.0
tempY = 0.0
for i in range(0,len(dataPoints)):
tempX += dataPoints[i][0]
tempY += dataPoints[i][1]
return [tempX/len(dataPoints),tempY/len(dataPoints)]
def numersum(testMedian,dataPoint):
# Provides the denominator of the weiszfeld algorithm depending on whether you are adjusting the candidate x or y
return 1/math.sqrt((testMedian[0]-dataPoint[0])**2 + (testMedian[1]-dataPoint[1])**2)
def denomsum(testMedian, dataPoints):
# Provides the denominator of the weiszfeld algorithm
temp = 0.0
for i in range(0,len(dataPoints)):
temp += 1/math.sqrt((testMedian[0] - dataPoints[i][0])**2 + (testMedian[1] - dataPoints[i][1])**2)
return temp
def objfunc(testMedian, dataPoints):
# This function calculates the sum of linear distances from the current candidate median to all points
# in the data set, as such it is the objective function we are minimising.
temp = 0.0
for i in range(0,len(dataPoints)):
temp += math.sqrt((testMedian[0]-dataPoints[i][0])**2 + (testMedian[1]-dataPoints[i][1])**2)
return temp
def getMed(dataPoints):
testMedian = candMedian(dataPoints)
# numIter depends on how long it take to get a suitable convergence of objFunc
numIter = 25
#minimise the objective function.
for x in range(0,numIter):
denom = denomsum(testMedian,dataPoints)
nextx = 0.0
nexty = 0.0
for y in range(0,len(dataPoints)):
nextx += (dataPoints[y][0] * numersum(testMedian,dataPoints[y]))/denom
nexty += (dataPoints[y][1] * numersum(testMedian,dataPoints[y]))/denom
testMedian = [nextx,nexty]
return(testMedian)