source: orange/Orange/distance/__init__.py @ 9753:5bd4ce14f96d

Revision 9753:5bd4ce14f96d, 9.2 KB checked in by markotoplak, 2 years ago (diff)

Merge. Fixed orangeqt Makefile.

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