source: orange/Orange/distance/__init__.py @ 9722:25e9a610d61f

Revision 9722:25e9a610d61f, 9.4 KB checked in by markotoplak, 2 years ago (diff)

Orange.distance name changing.

Line 
1import Orange
2
3#%s/ExamplesDistanceConstructor/DistanceConstructor/gc
4#%s/ExamplesDistance_Normalized/DistanceNormalized/gc
5#ExampleDistance -> Distance
6#Hamming -> HammingDistance
7#DTW -> DTWDistance
8#Euclidean -> EuclideanDistance
9#Manhattan -> ...
10#Maximal -> ...
11#Relief -> ..
12#DTWConstructor
13#EuclideanConstructor
14#HammingConstructor
15#ManhattanConstructor
16#MaximalConstructor
17#ReliefConstructor
18#PearsonRConstructor -> PearsonR
19#PearsonR -> PearsonRDistance
20#SpearmanRConstructor -> SpearmanR
21#SpearmanR -> SpearmanRDistance
22#MahalanobisConstructor ->  Mahalanobis
23#Mahalanobis -> MahalanobisDistance
24
25from Orange.core import \
26    AlignmentList, \
27    DistanceMap, \
28    DistanceMapConstructor, \
29    ExampleDistConstructor, \
30    ExampleDistBySorting, \
31    ExampleDistVector, \
32    ExamplesDistance as Distance, \
33    ExamplesDistance_Normalized as DistanceNormalized, \
34    ExamplesDistanceConstructor as DistanceConstructor, \
35    ExamplesDistance_Hamming as HammingDistance, \
36    ExamplesDistance_DTW as DTWDistance, \
37    ExamplesDistance_Euclidean as EuclideanDistance, \
38    ExamplesDistance_Manhattan as ManhattanDistance, \
39    ExamplesDistance_Maximal as MaximalDistance, \
40    ExamplesDistance_Relief as ReliefDistance, \
41    ExamplesDistanceConstructor_DTW as DTW, \
42    ExamplesDistanceConstructor_Euclidean as Euclidean, \
43    ExamplesDistanceConstructor_Hamming as Hamming, \
44    ExamplesDistanceConstructor_Manhattan as Manhattan, \
45    ExamplesDistanceConstructor_Maximal as Maximal, \
46    ExamplesDistanceConstructor_Relief as Relief
47
48import statc
49import numpy
50from numpy import linalg
51
52class PearsonR(DistanceConstructor):
53    """Constructs an instance of :obj:`PearsonRDistance`. Not all the data needs to be given."""
54   
55    def __new__(cls, data=None, **argkw):
56        self = DistanceConstructor.__new__(cls, **argkw)
57        self.__dict__.update(argkw)
58        if data:
59            return self.__call__(data)
60        else:
61            return self
62
63    def __call__(self, table):
64        indxs = [i for i, a in enumerate(table.domain.attributes) \
65                 if a.varType==Orange.data.Type.Continuous]
66        return PearsonRDistance(domain=table.domain, indxs=indxs)
67
68class PearsonRDistance(Distance):
69    """
70    `Pearson correlation coefficient
71    <http://en.wikipedia.org/wiki/Pearson_product-moment\
72    _correlation_coefficient>`_
73    """
74
75    def __init__(self, **argkw):
76        self.__dict__.update(argkw)
77       
78    def __call__(self, e1, e2):
79        """
80        :param e1: data instances.
81        :param e2: data instances.
82       
83        Returns Pearson's disimilarity between e1 and e2,
84        i.e. (1-r)/2 where r is Sprearman's rank coefficient.
85        """
86        X1 = []
87        X2 = []
88        for i in self.indxs:
89            if not(e1[i].isSpecial() or e2[i].isSpecial()):
90                X1.append(float(e1[i]))
91                X2.append(float(e2[i]))
92        if not X1:
93            return 1.0
94        try:
95            return (1.0 - statc.pearsonr(X1, X2)[0]) / 2.
96        except:
97            return 1.0
98
99class SpearmanR(DistanceConstructor):
100    """Constructs an instance of SpearmanR. Not all the data needs to be given."""
101   
102    def __new__(cls, data=None, **argkw):
103        self = DistanceConstructor.__new__(cls, **argkw)
104        self.__dict__.update(argkw)
105        if data:
106            return self.__call__(data)
107        else:
108            return self
109
110    def __call__(self, table):
111        indxs = [i for i, a in enumerate(table.domain.attributes) \
112                 if a.varType==Orange.data.Type.Continuous]
113        return SpearmanRDistance(domain=table.domain, indxs=indxs)
114
115class SpearmanRDistance(Distance): 
116
117    """`Spearman's rank correlation coefficient
118    <http://en.wikipedia.org/wiki/Spearman%27s_rank_\
119    correlation_coefficient>`_"""
120
121    def __init__(self, **argkw):
122        self.__dict__.update(argkw)
123       
124    def __call__(self, e1, e2):
125        """
126        :param e1: data instances.
127        :param e2: data instances.
128       
129        Returns Sprearman's disimilarity between e1 and e2,
130        i.e. (1-r)/2 where r is Sprearman's rank coefficient.
131        """
132        X1 = []; X2 = []
133        for i in self.indxs:
134            if not(e1[i].isSpecial() or e2[i].isSpecial()):
135                X1.append(float(e1[i]))
136                X2.append(float(e2[i]))
137        if not X1:
138            return 1.0
139        try:
140            return (1.0 - statc.spearmanr(X1, X2)[0]) / 2.
141        except:
142            return 1.0
143
144class Mahalanobis(DistanceConstructor):
145    """ Construct instance of Mahalanobis. """
146   
147    def __new__(cls, data=None, **argkw):
148        self = DistanceConstructor.__new__(cls, **argkw)
149        self.__dict__.update(argkw)
150        if data:
151            return self.__call__(data)
152        else:
153            return self
154   
155    # Check attributtes a, b, c
156    def __call__(self, table, a=None, b=None, c=None, **argkw):
157        # Process data
158        dc = Orange.core.DomainContinuizer()
159        dc.classTreatment = Orange.core.DomainContinuizer.Ignore
160        dc.continuousTreatment = Orange.core.DomainContinuizer.NormalizeBySpan
161        dc.multinomialTreatment = Orange.core.DomainContinuizer.NValues
162       
163        newdomain = dc(table)
164        newtable = table.translate(newdomain)
165       
166        data, cls, _ = newtable.to_numpy()
167       
168        covariance_matrix = numpy.cov(data, rowvar=0, bias=1)
169        inverse_covariance_matrix = linalg.pinv(covariance_matrix, rcond=1e-10)
170       
171        return MahalanobisDistance(domain=newdomain, icm=inverse_covariance_matrix)
172
173class MahalanobisDistance(Distance):
174    """`Mahalanobis distance
175    <http://en.wikipedia.org/wiki/Mahalanobis_distance>`_"""
176
177    def __init__(self, domain, icm, **argkw):
178        self.domain = domain
179        self.icm = icm
180        self.__dict__.update(argkw)
181       
182    def __call__(self, e1, e2):
183        """
184        :param e1: data instances.
185        :param e2: data instances.
186       
187        Returns Mahalanobis distance between e1 and e2.
188        """
189        e1 = Orange.data.Instance(self.domain, e1)
190        e2 = Orange.data.Instance(self.domain, e2)
191       
192        diff = []
193        for i in range(len(self.domain.attributes)):
194            diff.append(e1[i].value - e2[i].value) if not(e1[i].isSpecial() or e2[i].isSpecial()) else 0.0
195        diff = numpy.asmatrix(diff)
196        res = diff * self.icm * diff.transpose()
197        return res[0,0]**0.5
198   
199   
200class PearsonRAbsolute(PearsonR):
201    """ Construct an instance of PearsonRAbsolute example distance estimator.
202    """
203    def __call__(self, data):
204        indxs = [i for i, a in enumerate(data.domain.attributes) \
205                 if a.varType==Orange.data.Type.Continuous]
206        return PearsonRAbsoluteDistance(domain=data.domain, indxs=indxs)
207   
208   
209class PearsonRAbsoluteDistance(PearsonRDistance):
210    """ An example distance estimator using absolute value of Pearson
211    correlation coefficient.
212    """
213    def __call__(self, e1, e2):
214        """
215        Return absolute Pearson's dissimilarity between e1 and e2,
216        i.e.
217       
218        .. math:: (1 - abs(r))/2
219       
220        where r is Pearson's correlation coefficient.
221        """
222        X1 = []; X2 = []
223        for i in self.indxs:
224            if not(e1[i].isSpecial() or e2[i].isSpecial()):
225                X1.append(float(e1[i]))
226                X2.append(float(e2[i]))
227        if not X1:
228            return 1.0
229        try:
230            return (1.0 - abs(statc.pearsonr(X1, X2)[0]))
231        except:
232            return 1.0
233       
234       
235class SpearmanRAbsolute(SpearmanR):
236    """ Construct an instance of SpearmanRAbsolute example distance estimator.
237    """
238    def __call__(self, data):
239        indxs = [i for i, a in enumerate(data.domain.attributes) \
240                 if a.varType==Orange.data.Type.Continuous]
241        return SpearmanRAbsoluteDistance(domain=data.domain, indxs=indxs)
242   
243   
244class SpearmanRAbsoluteDistance(SpearmanRDistance):
245    def __call__(self, e1, e2):
246        """
247        Return absolute Spearman's dissimilarity between e1 and e2,
248        i.e.
249         
250        .. math:: (1 - abs(r))/2
251       
252        where r is Spearman's correlation coefficient.
253        """
254        X1 = []; X2 = []
255        for i in self.indxs:
256            if not(e1[i].isSpecial() or e2[i].isSpecial()):
257                X1.append(float(e1[i]))
258                X2.append(float(e2[i]))
259        if not X1:
260            return 1.0
261        try:
262            return (1.0 - abs(statc.spearmanr(X1, X2)[0]))
263        except:
264            return 1.0
265   
266   
267def distance_matrix(data, distance_constructor, progress_callback=None):
268    """ A helper function that computes an obj:`Orange.core.SymMatrix` of all
269    pairwise distances between instances in `data`.
270   
271    :param data: A data table
272    :type data: :obj:`Orange.data.Table`
273   
274    :param distance_constructor: An DistanceConstructor instance.
275    :type distance_constructor: :obj:`Orange.distances.DistanceConstructor`
276   
277    """
278    from Orange.misc import progressBarMilestones as progress_milestones
279    matrix = Orange.core.SymMatrix(len(data))
280    dist = distance_constructor(data)
281   
282    msize = len(data)*(len(data) - 1)/2
283    milestones = progress_milestones(msize, 100)
284    count = 0
285    for i in range(len(data)):
286        for j in range(i + 1, len(data)):
287            matrix[i, j] = dist(data[i], data[j])
288           
289            if progress_callback and count in milestones:
290                progress_callback(100.0 * count / msize)
291            count += 1
292           
293    return matrix
Note: See TracBrowser for help on using the repository browser.