source: orange/Orange/distance/__init__.py @ 9723:d0c9015bc73a

Revision 9723:d0c9015bc73a, 9.3 KB checked in by markotoplak, 2 years ago (diff)

Orange.distance renames.

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