Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/bottleneck/slow/move.py: 41%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

140 statements  

1"Alternative methods of calculating moving window statistics." 

2 

3import warnings 

4 

5import numpy as np 

6 

7__all__ = [ 

8 "move_sum", 

9 "move_mean", 

10 "move_std", 

11 "move_var", 

12 "move_min", 

13 "move_max", 

14 "move_argmin", 

15 "move_argmax", 

16 "move_median", 

17 "move_rank", 

18] 

19 

20 

21def move_sum(a, window, min_count=None, axis=-1): 

22 "Slow move_sum for unaccelerated dtype" 

23 return move_func(np.nansum, a, window, min_count, axis=axis) 

24 

25 

26def move_mean(a, window, min_count=None, axis=-1): 

27 "Slow move_mean for unaccelerated dtype" 

28 return move_func(np.nanmean, a, window, min_count, axis=axis) 

29 

30 

31def move_std(a, window, min_count=None, axis=-1, ddof=0): 

32 "Slow move_std for unaccelerated dtype" 

33 return move_func(np.nanstd, a, window, min_count, axis=axis, ddof=ddof) 

34 

35 

36def move_var(a, window, min_count=None, axis=-1, ddof=0): 

37 "Slow move_var for unaccelerated dtype" 

38 return move_func(np.nanvar, a, window, min_count, axis=axis, ddof=ddof) 

39 

40 

41def move_min(a, window, min_count=None, axis=-1): 

42 "Slow move_min for unaccelerated dtype" 

43 return move_func(np.nanmin, a, window, min_count, axis=axis) 

44 

45 

46def move_max(a, window, min_count=None, axis=-1): 

47 "Slow move_max for unaccelerated dtype" 

48 return move_func(np.nanmax, a, window, min_count, axis=axis) 

49 

50 

51def move_argmin(a, window, min_count=None, axis=-1): 

52 "Slow move_argmin for unaccelerated dtype" 

53 

54 def argmin(a, axis): 

55 a = np.asarray(a) 

56 flip = [slice(None)] * a.ndim 

57 flip[axis] = slice(None, None, -1) 

58 a = a[tuple(flip)] # if tie, pick index of rightmost tie 

59 try: 

60 idx = np.nanargmin(a, axis=axis) 

61 except ValueError: 

62 # an all nan slice encountered 

63 a = a.copy() 

64 mask = np.isnan(a) 

65 np.copyto(a, np.inf, where=mask) 

66 idx = np.argmin(a, axis=axis).astype(np.float64) 

67 if idx.ndim == 0: 

68 idx = np.nan 

69 else: 

70 mask = np.all(mask, axis=axis) 

71 idx[mask] = np.nan 

72 return idx 

73 

74 return move_func(argmin, a, window, min_count, axis=axis) 

75 

76 

77def move_argmax(a, window, min_count=None, axis=-1): 

78 "Slow move_argmax for unaccelerated dtype" 

79 

80 def argmax(a, axis): 

81 a = np.asarray(a) 

82 flip = [slice(None)] * a.ndim 

83 flip[axis] = slice(None, None, -1) 

84 a = a[tuple(flip)] # if tie, pick index of rightmost tie 

85 try: 

86 idx = np.nanargmax(a, axis=axis) 

87 except ValueError: 

88 # an all nan slice encountered 

89 a = a.copy() 

90 mask = np.isnan(a) 

91 np.copyto(a, -np.inf, where=mask) 

92 idx = np.argmax(a, axis=axis).astype(np.float64) 

93 if idx.ndim == 0: 

94 idx = np.nan 

95 else: 

96 mask = np.all(mask, axis=axis) 

97 idx[mask] = np.nan 

98 return idx 

99 

100 return move_func(argmax, a, window, min_count, axis=axis) 

101 

102 

103def move_median(a, window, min_count=None, axis=-1): 

104 "Slow move_median for unaccelerated dtype" 

105 return move_func(np.nanmedian, a, window, min_count, axis=axis) 

106 

107 

108def move_rank(a, window, min_count=None, axis=-1): 

109 "Slow move_rank for unaccelerated dtype" 

110 return move_func(lastrank, a, window, min_count, axis=axis) 

111 

112 

113# magic utility functions --------------------------------------------------- 

114 

115 

116def move_func(func, a, window, min_count=None, axis=-1, **kwargs): 

117 "Generic moving window function implemented with a python loop." 

118 a = np.asarray(a) 

119 if min_count is None: 

120 mc = window 

121 else: 

122 mc = min_count 

123 if mc > window: 

124 msg = "min_count (%d) cannot be greater than window (%d)" 

125 raise ValueError(msg % (mc, window)) 

126 elif mc <= 0: 

127 raise ValueError("`min_count` must be greater than zero.") 

128 if a.ndim == 0: 

129 raise ValueError("moving window functions require ndim > 0") 

130 if axis is None: 

131 raise ValueError("An `axis` value of None is not supported.") 

132 if window < 1: 

133 raise ValueError("`window` must be at least 1.") 

134 if window > a.shape[axis]: 

135 raise ValueError("`window` is too long.") 

136 if issubclass(a.dtype.type, np.inexact): 

137 y = np.empty_like(a) 

138 else: 

139 y = np.empty(a.shape) 

140 idx1 = [slice(None)] * a.ndim 

141 idx2 = list(idx1) 

142 with warnings.catch_warnings(): 

143 warnings.simplefilter("ignore") 

144 for i in range(a.shape[axis]): 

145 win = min(window, i + 1) 

146 idx1[axis] = slice(i + 1 - win, i + 1) 

147 idx2[axis] = i 

148 y[tuple(idx2)] = func(a[tuple(idx1)], axis=axis, **kwargs) 

149 idx = _mask(a, window, mc, axis) 

150 y[idx] = np.nan 

151 return y 

152 

153 

154def _mask(a, window, min_count, axis): 

155 n = (a == a).cumsum(axis) 

156 idx1 = [slice(None)] * a.ndim 

157 idx2 = [slice(None)] * a.ndim 

158 idx3 = [slice(None)] * a.ndim 

159 idx1[axis] = slice(window, None) 

160 idx2[axis] = slice(None, -window) 

161 idx3[axis] = slice(None, window) 

162 idx1 = tuple(idx1) 

163 idx2 = tuple(idx2) 

164 idx3 = tuple(idx3) 

165 nidx1 = n[idx1] 

166 nidx1 = nidx1 - n[idx2] 

167 idx = np.empty(a.shape, dtype=np.bool_) 

168 idx[idx1] = nidx1 < min_count 

169 idx[idx3] = n[idx3] < min_count 

170 return idx 

171 

172 

173# --------------------------------------------------------------------------- 

174 

175 

176def lastrank(a, axis=-1): 

177 """ 

178 The ranking of the last element along the axis, ignoring NaNs. 

179 

180 The ranking is normalized to be between -1 and 1 instead of the more 

181 common 1 and N. The results are adjusted for ties. 

182 

183 Parameters 

184 ---------- 

185 a : ndarray 

186 Input array. If `a` is not an array, a conversion is attempted. 

187 axis : int, optional 

188 The axis over which to rank. By default (axis=-1) the ranking 

189 (and reducing) is performed over the last axis. 

190 

191 Returns 

192 ------- 

193 d : array 

194 In the case of, for example, a 2d array of shape (n, m) and 

195 axis=1, the output will contain the rank (normalized to be between 

196 -1 and 1 and adjusted for ties) of the the last element of each row. 

197 The output in this example will have shape (n,). 

198 

199 Examples 

200 -------- 

201 Create an array: 

202 

203 >>> y1 = larry([1, 2, 3]) 

204 

205 What is the rank of the last element (the value 3 in this example)? 

206 It is the largest element so the rank is 1.0: 

207 

208 >>> import numpy as np 

209 >>> from la.afunc import lastrank 

210 >>> x1 = np.array([1, 2, 3]) 

211 >>> lastrank(x1) 

212 1.0 

213 

214 Now let's try an example where the last element has the smallest 

215 value: 

216 

217 >>> x2 = np.array([3, 2, 1]) 

218 >>> lastrank(x2) 

219 -1.0 

220 

221 Here's an example where the last element is not the minimum or maximum 

222 value: 

223 

224 >>> x3 = np.array([1, 3, 4, 5, 2]) 

225 >>> lastrank(x3) 

226 -0.5 

227 

228 """ 

229 a = np.asarray(a) 

230 ndim = a.ndim 

231 if a.size == 0: 

232 # At least one dimension has length 0 

233 shape = list(a.shape) 

234 shape.pop(axis) 

235 r = np.empty(shape, dtype=float) 

236 r.fill(np.nan) 

237 r = r.astype(a.dtype) 

238 if (r.ndim == 0) and (r.size == 1): 

239 r = np.nan 

240 return r 

241 indlast = [slice(None)] * ndim 

242 indlast[axis] = slice(-1, None) 

243 indlast = tuple(indlast) 

244 indlast2 = [slice(None)] * ndim 

245 indlast2[axis] = -1 

246 indlast2 = tuple(indlast2) 

247 n = (~np.isnan(a)).sum(axis) 

248 a_indlast = a[indlast] 

249 g = (a_indlast > a).sum(axis) 

250 e = (a_indlast == a).sum(axis) 

251 r = (g + g + e - 1.0) / 2.0 

252 r = r / (n - 1.0) 

253 r = 2.0 * (r - 0.5) 

254 if ndim == 1: 

255 if n == 1: 

256 r = 0 

257 if np.isnan(a[indlast2]): # elif? 

258 r = np.nan 

259 else: 

260 np.putmask(r, n == 1, 0) 

261 np.putmask(r, np.isnan(a[indlast2]), np.nan) 

262 return r