@@ -45,20 +45,26 @@ parameters(transform::Quantile) = (; dist=transform.dist)
45
45
46
46
isrevertible (:: Type{<:Quantile} ) = true
47
47
48
- colcache (:: Quantile , x) = EmpiricalDistribution (x)
48
+ function colcache (:: Quantile , x)
49
+ s = qsmooth (x)
50
+ d = EmpiricalDistribution (s)
51
+ d, s
52
+ end
49
53
50
54
function colapply (transform:: Quantile , x, c)
51
- origin, target = c, transform. dist
52
- qqtransform (x, origin, target)
55
+ d, s = c
56
+ origin, target = d, transform. dist
57
+ qtransform (s, origin, target)
53
58
end
54
59
55
60
function colrevert (transform:: Quantile , y, c)
56
- origin, target = transform. dist, c
57
- qqtransform (y, origin, target)
61
+ d, _ = c
62
+ origin, target = transform. dist, d
63
+ qtransform (y, origin, target)
58
64
end
59
65
60
66
# transform samples from original to target distribution
61
- function qqtransform (samples, origin, target)
67
+ function qtransform (samples, origin, target)
62
68
# avoid evaluating the quantile at 0 or 1
63
69
T = eltype (samples)
64
70
pmin = T (0 ) + T (1e-3 )
@@ -68,3 +74,34 @@ function qqtransform(samples, origin, target)
68
74
quantile (target, clamp (prob, pmin, pmax))
69
75
end
70
76
end
77
+
78
+ # helper function that replaces repated values
79
+ # by an increasing sequence of values between
80
+ # the previous and the next non-repated value
81
+ function qsmooth (values)
82
+ permut = sortperm (values)
83
+ sorted = float .(values[permut])
84
+ bounds = findall (> (0 ), diff (sorted))
85
+ if ! isempty (bounds)
86
+ i = 1
87
+ j = first (bounds)
88
+ qlinear! (sorted, i, j, sorted[j], sorted[j + 1 ])
89
+ for k in 1 : length (bounds)- 1
90
+ i = bounds[k] + 1
91
+ j = bounds[k + 1 ]
92
+ qlinear! (sorted, i, j, sorted[i - 1 ], sorted[j])
93
+ end
94
+ i = last (bounds) + 1
95
+ j = length (sorted)
96
+ qlinear! (sorted, i, j, sorted[i - 1 ], sorted[j])
97
+ end
98
+ sorted[sortperm (permut)]
99
+ end
100
+
101
+ function qlinear! (x, i, j, l, u)
102
+ if i < j
103
+ for k in i: j
104
+ x[k] = (u - l) * (k - i) / (j - i) + l
105
+ end
106
+ end
107
+ end
0 commit comments