Distributions.jl
Distributions.jl copied to clipboard
add InverseFunctions support
Simple implementation, adds no additional dependencies - InverseFunctions.jl is already a dep of Distributions.jl:
(Distributions) pkg> why InverseFunctions
DensityInterface → InverseFunctions
StatsFuns → InverseFunctions
Codecov Report
Patch coverage: 100.00% and project coverage change: +0.02 :tada:
Comparison is base (
ec68da3) 85.82% compared to head (6498137) 85.84%.
Additional details and impacted files
@@ Coverage Diff @@
## master #1685 +/- ##
==========================================
+ Coverage 85.82% 85.84% +0.02%
==========================================
Files 137 138 +1
Lines 8315 8328 +13
==========================================
+ Hits 7136 7149 +13
Misses 1179 1179
| Impacted Files | Coverage Δ | |
|---|---|---|
| ext/DistributionsInverseFunctionsExt.jl | 100.00% <100.00%> (ø) |
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.
:umbrella: View full report at Codecov.
:loudspeaker: Do you have feedback about the report comment? Let us know in this issue.
Can you make it a weak dependency? Regardless of whether DensityInterface will make it a weak dependency (I assume so), probably we will make DensityInterface a weak dependency in which case InverseFunctions won't be an indirect dependency anymore.
There's also StatsFuns.
Ah, I guess StatsFuns can also switch to extension at some point :) Made inverses an extension here.
There's already a PR for StatsFuns, just requires someone's approval.
Fixed those issues, and rebased to master
Bump @devmotion
Bump...
Bump @devmotion
I'm still not completely convinced by this PR, it's a bit unclear to me when these definitions are actually useful and hence justify the increased code complexity (in particular due to the complications arising from undefined inverses of cdf for p = 0 and p = 1). So I'd put a "pending clear need" label (as used e.g. in ChainRules) here to indicate that the PR needs a convincing use case first.
In its current state, it also does not support Julia < 1.9 which seems unfortunate. Since InverseFunctions is a lightweight interface package, maybe it would be reasonable to make it a regular dependency on Julia < 1.9. EDIT: Due to the dependency on DensityInterface on these Julia versions, it seems InverseFunctions is an indirect dependency anyway.
Any thoughts @ararslan or e.g. @sethaxen?
A reason why I have this in my personal utility package, and why propose to add here:
julia> using Distributions, Accessors
julia> obj = (x=1, y=2, prob=1e-3)
julia> dist = truncated(Normal(); lower=0)
# works already:
julia> cquantile(dist, obj.prob) # how many "sigmas" of significance `prob` corresponds to?
3.290526731491931
# requires this PR:
julia> @set obj.prob |> cquantile(dist, _) += 1 # update obj by adding "1 sigma" to the significance level
(x = 1, y = 2, prob = 1.7824982709635506e-5)
# can wrap in a function, still works automatically:
julia> @accessor nsigma(p) = cquantile(truncated(Normal(); lower=0), p)
julia> nsigma(obj.prob)
3.290526731491931
julia> @set nsigma(obj.prob) += 1
(x = 1, y = 2, prob = 1.7824982709635506e-5)
Most commonly useful with Normal, but sometimes with others as well - eg Chisq.
Also:
undefined inverses of cdf for p = 0 and p = 1
Btw that's an existing bug in Distributions, either in behavior or docs for eg invlogcdf (see my comment above).
does not support Julia < 1.9 which seems unfortunate
I don't care myself about new features supported on older Julias, but if you prefer so - it can easily be added.
I agree with @devmotion here.
A reason why I have this in my personal utility package, and why propose to add here
Can you explain how the code you've shown is related to InverseFunctions? Admittedly I don't quite follow it.
Can you explain how the code you've shown is related to InverseFunctions?
Accessors uses inverse when it exists, in order to modify values. For example,
julia> x = (a=1,)
julia> y = @set log10(x.a) = 3
(a = 1000.0,)
works because it knows how to invert log10 through InverseFunctions.
This PR adds inverses for distribution-related functions where they make sense.
They will work with any package relying on InverseFunctions or Accessors. As yet another example where this is useful, here's a PlutoTables-based interface where one sets the number of sigmas, that are automatically converted to the underlying probability:
Again, this only works automatically because it knows how to invert
cquantile.
For more evidence of inverse being desired for distributions functions, see eg https://github.com/JuliaStats/Distributions.jl/issues/707#issuecomment-481814272.
UPD: for now this implementation is added to AccessorsExtra.jl using piracy.