Mercurial > hg > medcouple
comparison pymedcouple @ 23:29a178b23219
Whitespace style fixes
author | Jordi Gutiérrez Hermoso <jordigh@octave.org> |
---|---|
date | Sat, 17 Jan 2015 20:04:46 -0500 |
parents | f5b4a2ab6204 |
children | cd3094a08e03 |
comparison
equal
deleted
inserted
replaced
22:f5b4a2ab6204 | 23:29a178b23219 |
---|---|
2 | 2 |
3 import random | 3 import random |
4 import numpy as np | 4 import numpy as np |
5 | 5 |
6 from itertools import tee, izip | 6 from itertools import tee, izip |
7 | |
7 | 8 |
8 def partsort(L, n): | 9 def partsort(L, n): |
9 """This is a partial sort of the weighted list L = [(a,w) for a in A, | 10 """This is a partial sort of the weighted list L = [(a,w) for a in A, |
10 w in W], so that the element at position n is in the correct spot. | 11 w in W], so that the element at position n is in the correct spot. |
11 Also known as quickselect. The elements of W are ignored for the | 12 Also known as quickselect. The elements of W are ignored for the |
14 | 15 |
15 beg = 0 | 16 beg = 0 |
16 end = len(L) | 17 end = len(L) |
17 | 18 |
18 while True: | 19 while True: |
19 pivot = random.randint(beg,end-1) | 20 pivot = random.randint(beg, end - 1) |
20 pivotval = L[pivot][0] | 21 pivotval = L[pivot][0] |
21 L[pivot], L[end-1] = L[end-1], L[pivot] | 22 L[pivot], L[end - 1] = L[end - 1], L[pivot] |
22 | 23 |
23 idx = beg | 24 idx = beg |
24 for i in xrange(beg, end): | 25 for i in xrange(beg, end): |
25 if L[i][0] < pivotval: | 26 if L[i][0] < pivotval: |
26 L[idx], L[i] = L[i], L[idx] | 27 L[idx], L[i] = L[i], L[idx] |
29 L[idx], L[end-1] = L[end-1], L[idx] | 30 L[idx], L[end-1] = L[end-1], L[idx] |
30 | 31 |
31 if idx == n: | 32 if idx == n: |
32 return L[idx] | 33 return L[idx] |
33 elif idx < n: | 34 elif idx < n: |
34 beg = idx+1 | 35 beg = idx + 1 |
35 else: | 36 else: |
36 end = idx | 37 end = idx |
38 | |
37 | 39 |
38 def wmedian(A, W): | 40 def wmedian(A, W): |
39 """This computes the weighted median of array A with corresponding | 41 """This computes the weighted median of array A with corresponding |
40 weights W. | 42 weights W. |
41 """ | 43 """ |
42 | 44 |
43 AW = zip(A,W) | 45 AW = zip(A, W) |
44 n = len(AW) | 46 n = len(AW) |
45 | 47 |
46 wtot = sum(W) | 48 wtot = sum(W) |
47 | 49 |
48 beg = 0 | 50 beg = 0 |
49 end = n-1 | 51 end = n - 1 |
50 | 52 |
51 while True: | 53 while True: |
52 mid = (beg + end)//2 | 54 mid = (beg + end)//2 |
53 | 55 |
54 partsort(AW, mid) | 56 partsort(AW, mid) |
55 trial = AW[mid][0] | 57 trial = AW[mid][0] |
56 | 58 |
57 wleft = wright = 0 | 59 wleft = wright = 0 |
58 for (a,w) in AW: | 60 for (a, w) in AW: |
59 if a < trial: | 61 if a < trial: |
60 wleft += w | 62 wleft += w |
61 else: | 63 else: |
62 # This also includes a == trial, i.e. the "middle" | 64 # This also includes a == trial, i.e. the "middle" |
63 # weight. | 65 # weight. |
68 elif 2*wright < wtot: | 70 elif 2*wright < wtot: |
69 beg = mid | 71 beg = mid |
70 else: | 72 else: |
71 return trial | 73 return trial |
72 | 74 |
75 | |
73 def medcouple_1d(X, eps1 = 2**-52, eps2 = 2**-1022): | 76 def medcouple_1d(X, eps1 = 2**-52, eps2 = 2**-1022): |
74 """Calculates the medcouple robust measure of skewness. | 77 """Calculates the medcouple robust measure of skewness. |
75 | 78 |
76 Parameters | 79 Parameters |
77 ---------- | 80 ---------- |
92 | 95 |
93 """ | 96 """ |
94 # FIXME: Figure out what to do about NaNs. | 97 # FIXME: Figure out what to do about NaNs. |
95 | 98 |
96 n = len(X) | 99 n = len(X) |
97 n2 = (n-1)//2 | 100 n2 = (n - 1)//2 |
98 | 101 |
99 if n < 3: | 102 if n < 3: |
100 return 0 | 103 return 0 |
101 | 104 |
102 Z = sorted(X, reverse=True) | 105 Z = sorted(X, reverse=True) |
103 | 106 |
104 if n % 2 == 1: | 107 if n % 2 == 1: |
105 Zmed = Z[n2] | 108 Zmed = Z[n2] |
106 else: | 109 else: |
107 Zmed = (Z[n2] + Z[n2+1])/2 | 110 Zmed = (Z[n2] + Z[n2 + 1])/2 |
108 | 111 |
109 #Check if the median is at the edges up to relative epsilon | 112 #Check if the median is at the edges up to relative epsilon |
110 if abs(Z[0] - Zmed) < eps1*(eps1 + abs(Zmed)): | 113 if abs(Z[0] - Zmed) < eps1*(eps1 + abs(Zmed)): |
111 return -1.0 | 114 return -1.0 |
112 if abs(Z[-1] - Zmed) < eps1*(eps1 + abs(Zmed)): | 115 if abs(Z[-1] - Zmed) < eps1*(eps1 + abs(Zmed)): |
127 Zminus = [z for z in Z if Zeps >= z] | 130 Zminus = [z for z in Z if Zeps >= z] |
128 | 131 |
129 n_plus = len(Zplus) | 132 n_plus = len(Zplus) |
130 n_minus = len(Zminus) | 133 n_minus = len(Zminus) |
131 | 134 |
135 | |
132 def h_kern(i, j): | 136 def h_kern(i, j): |
133 """Kernel function h for the medcouple, closing over the values of | 137 """Kernel function h for the medcouple, closing over the values of |
134 Zplus and Zminus just defined above. | 138 Zplus and Zminus just defined above. |
135 | 139 |
136 In case a and be are within epsilon of the median, the kernel | 140 In case a and be are within epsilon of the median, the kernel |
141 b = Zminus[j] | 145 b = Zminus[j] |
142 | 146 |
143 if abs(a - b) <= 2*eps2: | 147 if abs(a - b) <= 2*eps2: |
144 h = signum(n_plus - 1 - i - j) | 148 h = signum(n_plus - 1 - i - j) |
145 else: | 149 else: |
146 h = (a+b)/(a-b) | 150 h = (a + b)/(a - b) |
147 | 151 |
148 return h | 152 return h |
149 | 153 |
150 # Init left and right borders | 154 # Init left and right borders |
151 L = [0]*n_plus | 155 L = [0]*n_plus |
162 # (Be stingy, reuse same generator) | 166 # (Be stingy, reuse same generator) |
163 [I1, I2] = tee(i for i in xrange(0, n_plus) if L[i] <= R[i]) | 167 [I1, I2] = tee(i for i in xrange(0, n_plus) if L[i] <= R[i]) |
164 | 168 |
165 A = [h_kern(i, (L[i] + R[i])//2) for i in I1] | 169 A = [h_kern(i, (L[i] + R[i])//2) for i in I1] |
166 W = [R[i] - L[i] + 1 for i in I2] | 170 W = [R[i] - L[i] + 1 for i in I2] |
167 Am = wmedian(A,W) | 171 Am = wmedian(A, W) |
168 | 172 |
169 Am_eps = eps1*(eps1 + abs(Am)) | 173 Am_eps = eps1*(eps1 + abs(Am)) |
170 | 174 |
171 # Compute new left and right boundaries, based on the weighted | 175 # Compute new left and right boundaries, based on the weighted |
172 # median | 176 # median |
210 for j in xrange(l, r + 1): | 214 for j in xrange(l, r + 1): |
211 A.append(h_kern(i, j)) | 215 A.append(h_kern(i, j)) |
212 A.sort() | 216 A.sort() |
213 A.reverse() | 217 A.reverse() |
214 | 218 |
215 Am = A[medc_idx - Ltot] | 219 Am = A[medc_idx - Ltot] |
216 | 220 |
217 return Am | 221 return Am |
218 | 222 |
219 | 223 |
220 def signum(x): | 224 def signum(x): |