From 3a569386698fe4c7f019a70594d7f605d9236de2 Mon Sep 17 00:00:00 2001 From: Thomas Nagler Date: Fri, 15 Nov 2019 18:56:21 +0100 Subject: [PATCH] Patch 1.0.1 (#48) * Code clean-up and safety (#46) * code safety * remove dependence on qrng * some cleanup * avoid lower > upper by reversing the grid at the right places * ensure non-NaN bandwidth * unused variable * add randtoolbox to Imports * Prepare patch (#47) * code safety * remove dependence on qrng * some cleanup * avoid lower > upper by reversing the grid at the right places * ensure non-NaN bandwidth * unused variable * add randtoolbox to Imports * update NEWS and DESCRIPTION * update API docs * update CRAN comments --- .Rbuildignore | 1 + DESCRIPTION | 4 +- NAMESPACE | 2 +- NEWS.md | 23 ++++++++-- R/kde1d-methods.R | 6 +-- cran-comments.md | 5 +++ docs/404.html | 4 +- docs/LICENSE-text.html | 4 +- docs/authors.html | 4 +- docs/index.html | 22 +++++----- docs/news/index.html | 37 +++++++++++++---- docs/pkgdown.yml | 4 +- docs/reference/dkde1d.html | 10 ++--- docs/reference/equi_jitter.html | 4 +- docs/reference/index.html | 4 +- docs/reference/kde1d-2.png | Bin 19022 -> 20071 bytes docs/reference/kde1d-package.html | 4 +- docs/reference/kde1d.html | 18 ++++---- docs/reference/plot.kde1d.html | 12 +++--- inst/include/kde1d/dpik.hpp | 3 ++ inst/include/kde1d/interpolation.hpp | 60 +++++++++++++-------------- inst/include/kde1d/kde1d.hpp | 28 +++++++------ inst/include/kde1d/kdefft.hpp | 11 +++-- inst/include/kde1d/stats.hpp | 3 +- inst/include/kde1d/tools.hpp | 43 ++++++++++--------- man/dkde1d.Rd | 2 +- 26 files changed, 183 insertions(+), 135 deletions(-) diff --git a/.Rbuildignore b/.Rbuildignore index ee36597..046136c 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -8,3 +8,4 @@ docs ^cran-comments\.md$ ^revdep$ +^.vscode$ diff --git a/DESCRIPTION b/DESCRIPTION index cdddcda..b2a06a3 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: kde1d Type: Package Title: Univariate Kernel Density Estimation -Version: 1.0.0 +Version: 1.0.1 Authors@R: c( person("Thomas", "Nagler",, "mail@tnagler.com", role = c("aut", "cre")), person("Thibault", "Vatter",, "thibault.vatter@gmail.com", role = c("aut")) @@ -22,7 +22,7 @@ LinkingTo: Imports: graphics, Rcpp, - qrng, + randtoolbox, stats, utils RoxygenNote: 7.0.0 diff --git a/NAMESPACE b/NAMESPACE index 95e7bcb..9c19c65 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -14,7 +14,7 @@ export(rkde1d) importFrom(Rcpp,sourceCpp) importFrom(graphics,lines) importFrom(graphics,plot) -importFrom(qrng,ghalton) +importFrom(randtoolbox,sobol) importFrom(stats,logLik) importFrom(stats,na.omit) importFrom(stats,qnorm) diff --git a/NEWS.md b/NEWS.md index 93c62cb..99a3eb1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,13 +1,30 @@ +# kde1d 1.0.1 + +DEPENDENCIES + + * Removed dependence on `qrng` (#46). + +BUG FIXES + + * Fixed undefined behavior with potential to cause memory issues (#46). + + * Prevent rare `bw_ == NaN` cases (#46). + + * Fixed compiler warnings due to unused or uninitialized variables (#46). + + # kde1d 1.0.0 +DEPENDENCIES + + * removed dependency on `cctools`. + NEW FEATURES * optimal plug-in bandwidth selection for all polynomial degrees (#38). * avoid randomness through simplified, deterministic jittering, see - `equi_jitter()` (#40). - - * removed dependency `cctools`. + `equi_jitter()` (#40). * headers in `inst/include` can be used as standalone C++ library with convenience wrappers for R (#41). diff --git a/R/kde1d-methods.R b/R/kde1d-methods.R index 17f04f3..65bdffb 100644 --- a/R/kde1d-methods.R +++ b/R/kde1d-methods.R @@ -88,10 +88,10 @@ qkde1d <- function(p, obj) { #' @param n integer; number of observations. #' @param quasi logical; the default (`FALSE`) returns pseudo-random #' numbers, use `TRUE` for quasi-random numbers (generalized Halton, see -#' [`qrng::ghalton()`]). +#' [`randtoolbox::sobol()`]). #' #' @rdname dkde1d -#' @importFrom qrng ghalton +#' @importFrom randtoolbox sobol #' @importFrom stats runif #' @export rkde1d <- function(n, obj, quasi = FALSE) { @@ -99,7 +99,7 @@ rkde1d <- function(n, obj, quasi = FALSE) { if (!quasi) { U <- runif(n) } else { - U <- ghalton(n, d = 1) + U <- randtoolbox::sobol(n, scrambling = 1, seed = sample.int(1e10, 1)) } # simulated data from KDE is the quantile transform of U qkde1d(U, obj) diff --git a/cran-comments.md b/cran-comments.md index a14c5c9..99f62be 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,4 +1,9 @@ +Patch to fix undefined behavior/heap overflow failures detected by the +sanitizers: https://cran.r-project.org/web/checks/check_results_kde1d.html + ## Test environments +* ubuntu 18.04 with valgrind (release) +* ubuntu 18.04 with clang ASAN/UBSAN on rocker (devel) * ubuntu 14.04 on travis-ci (release, devel, oldrel) * win-builder (devel, release) diff --git a/docs/404.html b/docs/404.html index 7580fdb..ee5a16c 100644 --- a/docs/404.html +++ b/docs/404.html @@ -67,7 +67,7 @@ kde1d - 1.0.0 + 1.0.1 @@ -123,7 +123,7 @@

Page not found (404)

-

Site built with pkgdown 1.4.1.9000.

+

Site built with pkgdown 1.4.1.

diff --git a/docs/LICENSE-text.html b/docs/LICENSE-text.html index 8c567fb..fecd3f4 100644 --- a/docs/LICENSE-text.html +++ b/docs/LICENSE-text.html @@ -67,7 +67,7 @@ kde1d - 1.0.0 + 1.0.1 @@ -125,7 +125,7 @@

License

-

Site built with pkgdown 1.4.1.9000.

+

Site built with pkgdown 1.4.1.

diff --git a/docs/authors.html b/docs/authors.html index fe1e2bc..b076654 100644 --- a/docs/authors.html +++ b/docs/authors.html @@ -67,7 +67,7 @@ kde1d - 1.0.0 + 1.0.1 @@ -132,7 +132,7 @@

Authors

-

Site built with pkgdown 1.4.1.9000.

+

Site built with pkgdown 1.4.1.

diff --git a/docs/index.html b/docs/index.html index b9fe318..7f4bde4 100644 --- a/docs/index.html +++ b/docs/index.html @@ -36,7 +36,7 @@ kde1d - 1.0.0 + 1.0.1 @@ -99,7 +99,7 @@

  • the latest development version:
  • +devtools::install_github("tnagler/kde1d@dev")

    @@ -108,8 +108,8 @@

    Unbounded data
    x <- rnorm(100)                    # simulate data
    -fit <- kde1d(x)                    # estimate density
    -dkde1d(0, fit)                     # evaluate density estimate
    +fit <- kde1d(x)                    # estimate density
    +dkde1d(0, fit)                     # evaluate density estimate
     summary(fit)                       # information about the estimate
     plot(fit)                          # plot the density estimate
     curve(dnorm(x), add = TRUE,        # add true density
    @@ -119,8 +119,8 @@ 
    Bounded data, log-linear
    x <- rgamma(100, shape = 1)        # simulate data
    -fit <- kde1d(x, xmin = 0, deg = 1) # estimate density
    -dkde1d(seq(0, 5, by = 1), fit)     # evaluate density estimate
    +fit <- kde1d(x, xmin = 0, deg = 1) # estimate density
    +dkde1d(seq(0, 5, by = 1), fit)     # evaluate density estimate
     summary(fit)                       # information about the estimate
     plot(fit)                          # plot the density estimate
     curve(dgamma(x, shape = 1),        # add true density
    @@ -132,8 +132,8 @@ 
    Discrete data
    x <- rbinom(100, size = 5, prob = 0.5)  # simulate data
     x <- ordered(x, levels = 0:5)           # declare as ordered
    -fit <- kde1d(x)                         # estimate density
    -dkde1d(sort(unique(x)), fit)            # evaluate density estimate
    +fit <- kde1d(x)                         # estimate density
    +dkde1d(sort(unique(x)), fit)            # evaluate density estimate
     summary(fit)                            # information about the estimate
     plot(fit)                               # plot the density estimate
     points(ordered(0:5, 0:5),               # add true density
    @@ -144,9 +144,9 @@ 
    Weighted estimate
    x <- rnorm(100)                         # simulate data
     weights <- rexp(100)                    # weights as in Bayesian bootstrap
    -fit <- kde1d(x, weights = weights)      # weighted fit
    +fit <- kde1d(x, weights = weights)      # weighted fit
     plot(fit)                               # compare with unweighted fit
    -lines(kde1d(x), col = 2)
    +lines(kde1d(x), col = 2)
    @@ -207,7 +207,7 @@

    Dev status

    -

    Site built with pkgdown 1.4.1.9000.

    +

    Site built with pkgdown 1.4.1.

    diff --git a/docs/news/index.html b/docs/news/index.html index cdf9ea8..f2969b6 100644 --- a/docs/news/index.html +++ b/docs/news/index.html @@ -67,7 +67,7 @@ kde1d - 1.0.0 + 1.0.1
    @@ -110,18 +110,36 @@

    Changelog

    Source: NEWS.md +
    +

    +kde1d 1.0.1 Unreleased +

    +

    DEPENDENCIES

    +
      +
    • Removed dependence on qrng package because it was to heavy (qrng <- copula <- gsl, #46).
    • +
    +

    BUG FIXES

    +
      +
    • Fixed undefined behavior with potential to cause memory issues (#46).

    • +
    • Prevent rare bw_ == NaN cases (#46).

    • +
    • Fixed compiler warnings due to unused or uninitialized variables (#46).

    • +
    +

    -kde1d 1.0.0 Unreleased +kde1d 1.0.0 2019-11-15

    +

    DEPENDENCIES

    +
      +
    • removed dependency on cctools.
    • +

    NEW FEATURES

    • optimal plug-in bandwidth selection for all polynomial degrees (#38).

    • -
    • avoid randomness through simplified, deterministic jittering, see equi_jitter() (#40).

    • -
    • removed dependency cctools.

    • +
    • avoid randomness through simplified, deterministic jittering, see equi_jitter() (#40).

    • headers in inst/include can be used as standalone C++ library with convenience wrappers for R (#41).

    • -
    • (several times) faster pkde1d(), qkde1d(), and rkde1d() due to a more clever algorithm for numerical integration (#42).

    • -
    • faster kde1d() thanks to the Fast Fourier Transform (#43).

    • +
    • (several times) faster pkde1d(), qkde1d(), and rkde1d() due to a more clever algorithm for numerical integration (#42).

    • +
    • faster kde1d() thanks to the Fast Fourier Transform (#43).

    BUG FIXES

      @@ -134,7 +152,7 @@

      NEW FEATURE

      BUG FIX

        @@ -152,7 +170,7 @@

      BUG FIXES

        -
      • consistent behavior when dkde1d() and pkde1d() are called with non-ordered input although data are discrete (#19).

      • +
      • consistent behavior when dkde1d() and pkde1d() are called with non-ordered input although data are discrete (#19).

      • fixed bug in computation of kernel density estimates (#20).

      • adapt minimum bw allowed for discrete data to truncated Gaussian kernel (#20).

      @@ -185,6 +203,7 @@

      Contents

      -

      Site built with pkgdown 1.4.1.9000.

      +

      Site built with pkgdown 1.4.1.

      diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml index 2079fee..8999c6f 100644 --- a/docs/pkgdown.yml +++ b/docs/pkgdown.yml @@ -1,5 +1,5 @@ pandoc: 2.3.1 -pkgdown: 1.4.1.9000 -pkgdown_sha: 61c3999702966dd75267b98ce905df22521ebd11 +pkgdown: 1.4.1 +pkgdown_sha: ~ articles: [] diff --git a/docs/reference/dkde1d.html b/docs/reference/dkde1d.html index a05c856..9a347b3 100644 --- a/docs/reference/dkde1d.html +++ b/docs/reference/dkde1d.html @@ -70,7 +70,7 @@ kde1d - 1.0.0 + 1.0.1

    @@ -154,7 +154,7 @@

    Arg quasi

    logical; the default (FALSE) returns pseudo-random numbers, use TRUE for quasi-random numbers (generalized Halton, see -qrng::ghalton()).

    +randtoolbox::sobol()).

    @@ -172,12 +172,12 @@

    Details is the length of the numerical argument for the other functions.

    See also

    - +

    kde1d()

    Examples

    set.seed(0) # for reproducibility x <- rnorm(100) # simulate some data -fit <- kde1d(x) # estimate density +fit <- kde1d(x) # estimate density dkde1d(0, fit) # evaluate density estimate (close to dnorm(0)) pkde1d(0, fit) # evaluate corresponding cdf (close to pnorm(0))
    #> [1] 0.5008513
    qkde1d(0.5, fit) # quantile function (close to qnorm(0))
    #> [1] -0.001893213
    hist(rkde1d(100, fit)) # simulate
    @@ -201,7 +201,7 @@

    Contents

    -

    Site built with pkgdown 1.4.1.9000.

    +

    Site built with pkgdown 1.4.1.

    diff --git a/docs/reference/equi_jitter.html b/docs/reference/equi_jitter.html index a9f0425..908695d 100644 --- a/docs/reference/equi_jitter.html +++ b/docs/reference/equi_jitter.html @@ -70,7 +70,7 @@ kde1d - 1.0.0 + 1.0.1 @@ -177,7 +177,7 @@

    Contents

    -

    Site built with pkgdown 1.4.1.9000.

    +

    Site built with pkgdown 1.4.1.

    diff --git a/docs/reference/index.html b/docs/reference/index.html index 7dc1011..066f71f 100644 --- a/docs/reference/index.html +++ b/docs/reference/index.html @@ -67,7 +67,7 @@ kde1d - 1.0.0 + 1.0.1 @@ -174,7 +174,7 @@

    Contents

    -

    Site built with pkgdown 1.4.1.9000.

    +

    Site built with pkgdown 1.4.1.

    diff --git a/docs/reference/kde1d-2.png b/docs/reference/kde1d-2.png index accf458a68c4d5087d8ad8f903cd92f25317fe17..7bd3af737f42398a3744ff9a688c1b30a6eb1c0b 100644 GIT binary patch literal 20071 zcmeIad011|)<2FTS_HJVP#J5z>h&t1B7=-=(Nc?w3Q1&001*(G#SlygpjN0wp)FN# z07R=mLK5aF1Q3)sFgcurDG3-AJqZbjA&`*ddrlIn_rCYu-~0PM_mB7cJg?8whH%c_ zd+oK>UhA`l&G`fSJ@r2^`9w!YM}N=vyAJ8-EJ@bUS#)ICQs_5Bmy0K$kLB^-`z7k= zm}kQOEy#H_8K$H2rOuvR-}ok97jg(SF%f8<3TOSt+O@^ILcjiW$DW73q#s+D?6LXP zk>y_=UpKP;(BF(mlBIuLxiYP0SJn@^)4;aB{q*TCS)aZ$J@EC)ufFoVr*k>|tF`;? zF5dIyx7NSNXBFGVlEl}q6L)S*9JiD1q_Mw9bm{ev>KRLs_6*GO6AKkYnBf2Y_rDzY zUk?07IFOWa_A**W_c{ULO)>CGS_@CQg@XmsXe|xGZ<9zKdGJ$Jpljm5Zur?&Q%f?Y zUiekg-xk;mjqm5r+yQMa`z?bXc}ac*Yru*ye1pcAFcyTlQspI^6x-tA2ocZa*Lih*a zfrS|OGu`}$|HLF^SK-pAU!wUqzUfet+z6VwU>&S8>6QxT@ z6qk^*NcFyPrPiDb8T^h;fA=InCIyht@_0@lqq#|*Wb9TM6f=V_tP_3EvL^9k7AJZKXEdEH>{z0CvC=U>m?O@pmw@;}X7?`~ijlYXDCp^bUCR z*0_b-`}8P@4B5f)M$#zU!;Jb6Pch!$__9n(v@6xA)~VQu=EPY0C2X~Ig1;%`9KUuB z-;MNh9g_!^nCbMGF};1g%Uc?91jC11$#~|BECE-c z*>vXW32W{ieliC8Y_Wh5YbJKR>kp4^GuSYKZoYJR1$%!DcZ@mt;5=&){Ch}p;umPQ zY{RR^7?-ft*N(ZuzlEh`&0WHuDFrV$H?S1slI$rQ_iioxEZuy68$H=3((%jj5pWK? zj+DQP1zgDyzG7;&30pqCJZdrgTG9p)f{Ny2?>ZInC~Mm|wdVxqvaFNtrq+%M zk_W5w;5UNHdSV`&@9|Gs>wLw$d1~SjXv%I@9>#`rtc{kIx3oCL%nAK~2(ocZ#A$e0 z9bMAJqzShp-D5$eg@NWZnev|KH%vNNcF1FbzIxy;yz8$A?mC}`kELru_uNKOp55Gi zE=NEvxiHm1F0pR-^Bg>uQus5Y;OEzd38@lgf-=q+sXo~i>)za@r{FA^diBYwOp-2Q zqt%`3uK4dIiq#a!I6qmcFIFE~`}HH}7P6_obzswdxw~C9&hL9W!gLK-xtcaxah?rp zQu?Coblj}6MfNlJ7@BN3f2K@de3g}hiaXw$**Z=cLrO{3MZs3^&Kz$nPtFr}>l2fE zOAX3m2S&Kg2t&)UJnOphp&4HZ9a{W(M!J-x(b4opmpxc@?6-g=N>y82GR{WXP^hK* zsfCP(Q|>_pjy=4V8zyQQ91dkKWm^IIQ5g4F!`>n!BfQ%cRmX5mE;$*}!H!q{S3yAP z#J>-0;$x50D_SfA&FfxE%IK~H8n`G5BPOLbH6_Wm!&9dh>}sRC7Pf?^9`krW5NEXE z!dz|xi=MOm2^9koB-QU68oaTu7jnZI8f7!dj8pZ!1~gG~raZ`pL6YTycXk`AjjV9R zLhh-?)Mi#w`RLd7@R;-=_*BC`=~ToCN6^_cs_5B-LPZBx1C)T2>6f52e=cqVZ3X;B zx~uFm$N;DuYAdY=tkWe?#?ILFj_)$Ie=fS=2*0pss8N6C6TipSM>jsZ86uwxmQcZK z(uo0vsq)*_9jblmS*)Jk3?ZbTB?L-ptGf@QM8*VbkRCkC*cnuo<$!3Rnw$OA4z+{G z(JqS&Cj;0wde|L zcsT4X_lk#%R)m7%sJa67pYy$kqzH#y@ns10;!ca3vvA#4XDN_ACrY{!Qhg=O@H?FC z*_m5v)d=%&W;$-t4U!knYFO0?n)BzFB;CE3RRJ0Y70iOCn7lgMTRWJ8TjyQY(!X*` zi;FJR>hTY4gg1xCYBph)B^!&cg1yYy4zhb`%Zc0w>#{=Ip4K`i8)9(Y=<9@fdt%lx~`g&7i z&4PH1Ar4}1L=wIhf5RN>~T_VW353v9}J z4bJ203{^T;e#QG87Pl30~kOqG9 zdxFPn9EpZu|6=@YU780AW=K9v;y-6)e?Nu)*O#z82u^}{UwO%`Sp%5DJ=^q5pWRWb z&;Ybxr&d^((~a#nXlSo9KqoCYxeFVOed*X*+*BtE#7aID9I1GEmffp971ir%22(d8 zb0`*moO-7gr(*>KcQo3UaU1V}eQW=m8KZG4Iww;kq>Q$Bwp*YB%7!Lt;hggpwr9}B z<{)smJI~=cAt%fjb_^9oJL}itc18`H6CO>1v|1M#N6H==R|rU(O$N6GBG5kOXmcM9 zr5M|Bkk82U^(I*$3l0*GKH2S~S*h*9a_ERr0YQL1&fSkuhYyu-k&EuR?krtvmU>ds z06qtQ1e?M48R_}=pQ?GUV-VaMTie}EHZ?djWSr^SS`$tw*>{LDJrrqWVjWv5eK}9s zlbaz6b#3VBi`uU6XU>D?0b^-GK>#TNA^sxBU1Y$z&pM{DWzjGVe($ z!eA?VtzOnacB202Z=-|fS@JnYi=9vK(b0dZ!N4lWSiR!U+&Iq)@EfZ-&k7CQoLR2j znGiM}XA)9;v7P3D0wv(XoOKqD_(xyVz`3r=kb%NHUHPd+U_ns9v*STrN>ha70>}Xl z^6{;%As5TNH5MTH?dGOrV`MK4bHE(wifeZBXHbgIbs+fIeb_uOf6|GHKZcdXM!C^s zBQLx*YE;j5!wAP>%(sY)c@7pwm1MKI4OBc{;{5DV=LSgcWqxW~kW_Q5-_53Me>vtb zx;d{GM+!c>86`bgy#Ju5vt&j`B2~0(FstNQP6}!T9U0v)_&hr z`f8PPZyVhu?=KCU)1*7vQ>-;!TB-z?tU@hg8W102lo7@%T~pjUi2 zLJ%usTUV2r$eeOffO(L4O%J0e_RU@SWl$fuJ#@gb{`PJ)Uaej~!f|7wT78K@0dW@- zawhS+B%6Uoecc)b|Eo`q=FBgjjw85K;C-;evEm>U`bl5*C<(j@z5(;WSbd6Vwu#vF z5BwoX1$Y5mmt}ob6N>!*QAYo_cLfpfDNP?3I8N4?=HwuyCS$ZRk&kON9%q_KN6<-9 zR4+{wqf_0*xI%P;a zA+%)4Z7p}bAlJF^BLCDlp@Gg4m@MQHyen8p1zwW7ns!QfPhj=4#{NQf!J4~@pFF-x zKuk5uxqgg6X{eHwoM$>InP1(g4nl9Kq*fg*d>U$ zzmsowPS4cfr)z)PimAEu<)GHuGuK9C;qE%Rk(~GjRICat%qKRxNM}Kg$t3)flGi8AdxA!1q_+^I|kZe z*uJ>3>@_q#Dbv1Y$6>)KK-W0PN$cabEf7yTmdFAnH<5;DXKeFyCl+`{=3Sxgu&?}J z+-~jem_D@!dqmO>zF?$GznE;y{Ztg|p!Et?^iS*Ap92GY>>+F`_&eC2!CH}tVmk<* zGpb~Vu?MjaxBq-w6QphpUC4da_?Nrm`@hs0)|zAK7qzrlIVb1w$z=JC6qSl9+l3Vv z6}dJR7kB`?y_hxh#0MrYbF0_a3}SeP7^Sk;9Ih%^5=2HJ==Og6+ki*s>^D9}Obe}* zh>m> zjXPcLr8N-)R!y#{#ZJ-JRTvLTjxAX=+*dcs^DQ!WPdgzg7(#z3&~7XMibv&D;6eVJ zt3ExEHZ)%79<}UL>pWsRu~Xv^)q3Pmi~nM9CnfEt!QBwo<}83`#(~BGp<3erMFh=s z+Lg56TtXUIMo&=M0+o7YKQY#7Irh&X8h51zGpOm9xjIX%k5`$JaTlg6$rf8r?H1~5 zJ-QVfl{SYf6DiYt&I2EkjlIx>c*-C!V8gsL;TL=qvyN%W5?ufl`>ty}kk~oPMvfso zZT@hwU-u^&L;Rf-B}rvyCj^NENfbb2oqFv+s?VPC^fgBGl3Jn@!m4yXoHJLhk85L7 zLJDy#gVXGeC}`=itw-_@jMNn3x03b@b4GO0rF4{`1_gPx(TSLYt`+!wlG|2piJ_92 z3@)R{?*KYFI&7@gT%7{x%0{0b5_AAkR3@SX!9-aOzPu7Z4k}H(E#rdMNV%k3W7LMI z53VSW-w6_-z_)j9G`W&EZ_glex=o8J){mUKNO?a}J7f+iS~_Gn+dH+`1#(t@_tw0| zF0lD~r`6v1cZRpUQ;S{x-S`jK#T=ThOKTV)1vJ&dz<`CA{`^19PGb**fFg9yC<6(ExNi+ zB3571Xz3)^gR~K0NbV_ht9o;DHe$1DvO=xI(5A`%n8*TxRJ`1?Cheo1s2uWs%Kp+G z^8UDGKl!;>sZHRBjzowY+S1%K`eiLK;d_Z!6bnE27a*p!p#SD*jJ}=wk%4ot)P$Zj z$MW0muBJ*5tEsi_I}^>^54u*$Ubs;cy`ad+oG)N#5?$X9^(E*uAc=&K8*jZ^LfR#TWzE)k}+>*?MHB8KnQih^9R*ITCysP|c#6X-aSvQH93%5e}1(FBga z!cX_RR<7=j_wgJA=fFqUPmk~9fGXK{n4i>CF&gEV2El458TfpTs0pEi-A}}NygtFI z(hEs6Bw>d8sKL?-sn@tlfls3jrEx4HXA0+{B`-k&DHFxxtV~hum29Rgy%|NTuCJfl zGk!0ft%`=Xac5)Vz-a@jg+HT4RuXF&h zg3EQ}_3d|ovt%(viN?-Zh-Q7UK4e9t7{#FC5t2V*EtiUSp?1`u9Oqq zP>nZRKH$wcTkR36d5|vc1J?pq^c7(_LmjR~<;vt{<%tyWkO{u85Lj8N2=1UsT9Z%L zT6e5p9*g_=Qd(et5MdX*l?so2kifDs&bIfIw~(E}4W)CujIX6RBl|~a)iT&zSTicd>YbIJq_`TTo7H;$!;DD4?*T4;OcrPICCB(k1XmzT=AMj}9 zt}_{Qn!{pew`V!EY3(npvX=ehlJ%5~rZh%Q6xT7^a*%y9{Kenr6zj(ddei(ADU#`j zW6w zV#ng2>Z9Yu1*FWJDKFyyqo`$??8a?qr294u;hhK!l{bi#qW549IR}~MjIp7lHaRuo zlO%ekE~+WuJb!LHYjZAVe%z*j9nHtgXjkLA72QvOEBx9QEacGV*Pr!Ojpif~L^Yrv zu)337M8Q-wY#-?Uq0Kq(@&;HW2lkmBRtSHL8jr&S7Hr3COd1l)?*buFn4+ekYAMOB z;_orFm@h}aV31>D0Of^Sz6K@#M1+#K!G$~ z6-7cJ(hhNI-Yjf{&vdhydi19)i<=z~Mc0~E=FbDJlaMD(H~(4#T(-pEyq}yUS(aJ^ za&F_(An*wc1?mbfegK7Gt4;$@data7Dtp9nbEe5ecC@ro{CAR{K)zn-k~$v$ zBEQI&)<0e?K5Uyddv*3Aph78_;LGJvS8`PYeOWW*P=xnulp7(ULz;dnVEG&KDmWw8 zR=#)5VWPxQ30SxhCLEO>5*(d4oz^)?-cTMEOD)F?Pi$7EAM8@$h370l#m=CkndpCXjIp!F`x#^ z#IgNl^b&zHYgoDt+UdEB;Cuz|oW82NR}IwM^zG74&I6&Imq)74vb*7WAaQv@P};arLuq>ZOZSpk^IN7IqTSy_!LPWC?IuAzZ)pZ zZ!v4=n8!ho;!2S=*l!5CSu1 zPOA1dZ0NfC5vYa$pQR~Nz8C&A1)ydW<(<78s0W*dxoXJ&x_`kGchRbs!gvcptIRcX$_UeWm zQDcTLZo;i=Nid6}Kq>i#*NiBVO?1e`)f>un@BBq$0FxjEv#h=w;d#+mIG-hpm^Vb> zA99HK+skEj%h_id{XV$e&_^Du;Iup1l-IhEbCgw@P{KJ&v=N^JDuE|_N!6s{ED5cr ztPc4>tNRfLos-jUKzQ^WNC5<-JnHP65R?FG^kh>Z$001QJ%Z7D%_ku2R}7&pJJVrY z3CKglQ8CXeZW+IxkLx19bSaxGwiv75vABUY+(FE%Yg+ei4UksUV2}@$2Vfp428pIJ zP(*S=5T|C8^|VuIlw5Mo1u^e%L4#{p)lp;nIR~{Fx~<|Ikh147$-PGXQy(x%4&{pK zfTY#FQMDRaM-rI&+q=ZH`v)J_;&^9Btec&aY)X~US-pXn0*9W~RQRzrSb`r1xn`#^ z@_LCU&AhKrKg++a4MDGLA5j?dlND}mxc5KSwmsKsRS%>-?%8}Igh(!Vklk!UthPdB z4OmU8ZQ(#5!Q~c^qlT9nEFv_1d z=RLpESE-uuF;F8#5XzFIQJn$z!ECN1&J%$5*FJtcs$f})~a`8_Ybw+>JGZCvzCJAS- zQ~xdk6<*PD7|Pfd@lE|vDM0~ZVhWsz?Kq7cLq<5%GzJqO%aa-ovo-%BaXDF;^zLs^ zP3&}(&9nc{@YC+So!c$hgPU2e?LW#=^h2;9Y6Iivka!dfD5+6r)_K?23 zkr6-h1mKf=$g4?Hq-UlJkJM#qv+O;PJBKnZQv`dV3tG?wR%QG$MTP7z%c{IFS8)tW zOHf_~9|FepGeRn;;7iVc#^eZO3FN*pE|IsRcWG=?s(2It^zXjhNVXJD$1HCtha#W* zd?Fjkt0btHBI+b2dS|ILfNyoW7)}Rru}n(>RCcis$ns3CH@iahhsL zfU7WSv*;j$S{xxHkO-(&KVo>j+zq8j^&n@uQ?jG`2k`BXPkHzcy&Tb;52n@>(tdX! zervxwg6G4jc&KoIB3PBrr!=x8c2AyV_Fxy%HI_+ zqCPq+kG?r#JpL-t(wwQN-QDq_BP3vafxO4L!H57=r64J{3HPpXf7s+D!&NO2=#qJ1lt!)p-I;WgVFMa}lCL z#G$KWQqO;0^5~Gh{Kt|<#KlV;WpGV7?Ml_|jyPX-&eTTVG=E};lQcC{k_}Gs1vZFQyAZ3y z_rHPnz;nQT!mRK>dLXxZgds#^f3=7u|NqtkyW$P8cB!mXYp;djj~vdoy7#H649 zd09rEnC)i(abZq1&LRFDa|+Fy#c>F7ZtBfz-`%*hbUP;lbH?h9>5dIftIrs^TwJm0 z$`_dl+s-bk+K_Fy>z6MdeY)eP6-`)4t-Q7&~hwCJ6gHJ04dh(-`lY(XsxLqHYq2BZN}R!a$(m@1b;Vf_Z?_-n%0 zC}88uW51(pYYDF-Mo6*%Q&Xd3^10a09zY2?*dXnN`c&dvTJRCr$xTJ>P=^py8@dD5 zfoH&PfZb4S$li$T90_NHpqe1qfmB>?+Nv7H6Y=7Siq9_*O&vYCz9q~gHM1glC&P%5KxODR^U%T zIX zJ=$&^JGN**G0lkhRb8Lo;CZ-K?l!bFOL{HoO^WH*Y?nbn+!~dS#Mb#FRf^yp=2Uo$ z4Q&qBU=VmhX$#b!QwI2uaGcCU*E+mXIKz-uQW3<2%${ma`w1Uyo5hJORdsR50+ ziF=Sybt;G(hJM<&NUG3xjrK;i)||Dga@Cxq+|Z?B5xogw%g^Akjx%946gMP;4i!50 zRgc#}eP-WOkH3IwxQLSLQ(-_RuJxqR8%YLs-B@$$em1GTK(HPZ>~d{`$q;tS$}i+YaS{Aql~c^34|5 zY|$FXm&=kvcK#`3y~hJ@?nY_354Czc-lhS{54V{nNDBhcHC|)NF6)9knifo+Slmn( zi+$q;Zzs~mpPri4BEAitSs5H$;*^pi3^H9nbJ(q3bwvmuk{3W&pqh;G9kX(o=7OSa zKOYG*UCUUbIRbDpV)y`*ck`BrN!1ZWDjM08`L~}hX{!(~k3FfVR}v+yIq1a^T9X6O zFXaX>tGrUo)0p=9Znnt6`5lhw3DtFz8 zIrCYkb^0Z3MhxOl@W;$}qTM}I%Qzt_81MeT$?KBWYiR;Fa!lW|()aGW_oM38h(i#Q zU9?F2GlTPvH^fRUxY`7@rD&4n>3g7g-)Ym3>XF*x36IoP+5dpVb4n{7c#@%I z$r23}pF&GDe-JPHRh!|?|99g*h!=`;9@}a*s3t^fhMc7LI~DfqIm8nOoD)?y1kU_5l($UEB`F zbVDt{h}MIOB+2R5#iQXYsE|?u)gvu@TyNqDScJ#dU0kir+4Q*XlaVecxB5~z(+%7r z8zaPVg82I53|TN#`KbiR5k;-dcTMWKtU29)D~t8;uyeb;o(;OWH5tAD5Lbn)z>Vc+aW$4%5C?Vk3g6rQl`h1}e1HDAhQCRRFW zO+7r67PoAvAwpb=8ECcZBV|U=#UK=>ZzkOWyds8}B%A}( zL>yViK^6qL9;-tKx>h!UzbCeo%O*s5J)1sonZUmU=|I#~o2Kdffx4ghKn|+4Iq`Po zLM;_HcXx145wVdH5;*vI5n)_-DsTO;d9Eh9*|Y5|E)E^UI9i8Bq7R}mu74EUbqoLn z`nK4(Qa23R2kr1(rJlt>*GB)L(}}Lhb-bK7>*&SJR8v?08@@SUS12%XZ$Pu$DTOT^ zW6ei1d+Uwujr`^f!ODrM3v5IYuQ-wD-LZu$z`aQ!?9t?4HtcS5cJ(C19e=|n#Coih zF@Xrr^0&OMx`K%r$m>#J-~N$OPg1HCR{E}3hr}c(SCNA>9DF(H4z;ez6y~(-Fpa?- z(eW>e5j%JDjqMgU2)v?cgX2eV1Au-I)49|7<%$%d$9Rd}TNo}L=9-#TU5>~>KS&K< zD&EmtCKKpcrZul!#-N65t7=7}cM^p60b>$d7qpd+bmE4b$I$Ak;t=o)3GHOPRBIH3=Ng69fngy1Ya z&^YMfpQhZoCGOg|iYT$EUn9>3&sOs{j{EPv-gABc6SZ2yOQTH!bib7IajT>dzz z*r+aC>v6ssG3P;y*_dahdOM(;E3i2?kFq~oAfB-|65=O*<6CYUO2a=sC|vrdUYhg7 zJ=5Ni@{x&h&^er0G)y_;2-TtC)nJ7WKq2BNsdX{}5Jcu4KnD?HB)LN_suHqS1hci( z%kBhTV}jEc9V2FqAH}lUnZ1KAXHm#F%om9s@_Jn{#Pbd{&#$u&$j3v~U3Bs86P+35 zuLeSmtBS6iZ*ah%&~8K48};vGFiyGsCd3H{1ESxL+G)Jp6Q~Str_Io;feiFT&5?QtneO9S0|gcEk=0MmvcHOg z$6wgrrbnJfK>zTTwvj`-ptkWsv*4C0t+a1JJ*CIBJq+-RCR&NDg~-x!U+DYei(!p#4Ili};;n{L%=WtvrfMT7g*v}=#T zzoGpD&Q=qguNkbC?myolN8s`+%%5EOR=c$Q~%Yk}d$~a-ek7W(TQUWOwU5bT2-?t-A7-};I@)nIarp=|U@T}( zLvVbId6>AJoJ4Wt;Z5Rr4)za`OQ6(jO}5x6a3c%!s*hczv>-dT_-<@D`N&i!6MX51 z9qVK=Gu>Z%nOYXvrp)E_(1x&Od&R=k(FU!_RB8N!k!wKR0|aXYr`hp%14k1R{Z@oXdH-oEaA-_F$DgaHxLt|l@W z2?ev$-GKYyxqG|yAId(-?zX=i?}ZhA!q2JS^%ZC3@i;RcQc$u%kO^`*C;J!QHBFJ5Fh>ut)?rwYi^8t z&Z#ea-JPum_Dto`1CySYWIo2P&ne}PS2r?PN`p;!%Ql!m+Y$*c58< zXmk4#f>?Ro({bXi4$khl$YsfvwTs65SyTQy*)9~?wQ2L;&oJx+LU^PPTU*U=G0qK7zEWhj>Q>!?dwB!eaLn;EWjiik-v zr?Cgm`%vHJVqYFJcdP5OO@#`Ra6n*-Ji}8#tO{{ZbRyMuyni8Dy*(m6j^!tlnzpzq-Q>-O6h_(W#6O$i$LKzy-|61uXE$esP;;yl%7qYY(bx^SL(i! z%A~vPQ{K=01Z1L3^xJZ$lRfR%);><9L(CBcOcEiA0tWFFgQdO)quJ z-&qTOgVLpP({RV@<*AXnnj3-BYvH^V06Zq6cD&C^c^fT1ED>cG88~#;4Vf5;@O{zr z2K*5$uxTvC4_^w~;I`8nM>wXm^4N0Bvy@-&FuUpyW^r#qikMY5Y#=3!vvxI z8KkD9`(qeq0yk_qPHkV;{5P^X>hj>;Yw0)__WA}mub?AZr12;^)0;FHqRnmoMr(-% zy6DK~Z?qO^K)8<3N8?D+iSsvFy*1uIXS!@%sBznA$x~3AgT7~PUD`r&@}uMg>g@$a z2b3>M5p5^Uuf|}!f)k_kY3rpu_9L55S)HcDG+!P@5<_14ALe*4tw)q!w>`$lUq-7C z)iLhz1#Q#As}=@K`7aD`9-iCh5u6B(k23DEpDvQTKD8<$I7Yb8@fYO}a=z|N+5yH5 z=pGQ;le*;2o6~?Z=^8oW0=&9A)b=Fv1jHAiFHcG?7FX-&7%YJQF2F65R2Fn^hcyw-@VYqer8yWZ0&UayLyuI}$TSFM-?o3`nlu57rizJ(e5 z-(cl`L>~WklKo=Vfb#M|a{Ak*TTL6;%cAc`Esq{&9e0I(e0AApx-Bp9qE5X3n6D}f zds6sqaJxki+AV3-))2$;!mAEI$Y#}U$xoG8>C5FHIK;GGxIwfBI17Ekdi6ixU%G9D zebR!h+fWF1U&T218<-6?L1kihTI?Fyj{NcxgkgDV_2|_F&~+OcG7n`~3KgRcO73sV zI&(hx0MxI)31B0Pkws<78t6JBisWueamud~Q?e1_nBC3nNUH%^WSzJD;kmilVA;nQs>|b+%I7E&)#pw$k4&i{671gs$F(}LqDlUj46_sJ0Z9R+QSN5*IcV@RcYfcs)6W^z(@8(VP zAE#H#l)oPTaU0R2qrk$H-CnDY`<~G-nkUJ5|BC%+s&muo4Q~?w^z!6lumC!lj`uyt zL#9f8D}6L+YIg*p^~v1*(R~De^S$iPyJ=8AkuK+R{k!9xl8HiaIn=M1Wg5F%)p3p~ zrnZD#_%>vh_;{**bFq{Bccvl2Cg6+2P^<`Jv}`r@n-0^jvQA%0&pRvhHl>~oFcDoJ zjHMsBzI{QzmpgAx_jZwUcm5Q~ySwu`bOHU^)8G@g$;1pwf6<0L{UbpI02I+-*6Zz%_H}A8*fQkI|HEu5h`_f-0|Cft6 z6^l&c92q7XcPbuOJYV87qcJP2oT<%62)|;-WWBWBGGsSCxV|s$pi0`2?TNJ z=XZCwq>Rqo^17g!YoGkp9MUAv&_s5~y;z1Cy1;-Q4Wdc9cSOS(*spsc^M87Gi+_1h zZsm*#6#1-a^^NbdYH^IV5zf(s=EYmU@|` zsZ7*D8#SJmWYF&vZpHX*B}F)-QIfgsW2%GriFUC=;36C%?FlRD$2p{=E#c9RjIgDU zm`~|39jvw~JD<52>(ouRrTA6vO?N8PxOt+Ne0mbijYmJ9xH|cG z9n@h^lVB`*0u}>Upf$EZz;`EG@S1PGz&Y&w{?xY~U#@6VJg3>G;l$3DzfiHxP3G|K zHwCwDJ!@Qt`$P6?#!!?4H7|(F>fG|lh8G$3MOaBoOG=2nbzkDx1ppl~|MJL<4m z#5O4DW3LKZY(VmW{xXC3c>cNC1j=yV)+uv?pD*(EiKt51h8#U;a%)m*c%5t1wMzH? zIeguu;A)UVoN1#` z|K{FkB~i7yWDV3o^NM1(C7hnno$|QhRhy`)LRXigug5g>KQgylkNNn$aLGupA33!_ zmiwBL7E8u(`)oz^otyNgFBO%?LicEHIYr&`54H(Bzz9j2BLGp~l`j$5u*hU%x0dMg zZ*}^KD#R4-eQLtB%BXJnOiFB?;EbYu1t#CwUlBVM^gHkjI)^z&Gb}oN@wH% z^tUHARp-#kl=KXiTU&h8>?M72ei3hC>4T~*-!J=GKQ6;8a#^%{?aLW`w)ltLTUWtm z#k;GHMxl}{SbggfY`p^SRdvtA1v<9KYHsN?1SKP; zhU_uPSGQ%Frmh-jc*UZe*$VY^LYJ(Hq8bd`ICHUv!J^sjAe+>fYn54>i(2Dg7TxQAZp(7ttB4~Y*X)HZ8G~ZGRs)R7 z39GFL!x-fhivjTBrj`^H9pntpUBwS>2pzfc>BNb?0tB&T7CZ5?eb7%+Z}qL#*mn}y zn9rAmLN~BM8sfqe7!NFjqd$@e_JLJ zQ)#Ire2j-)M%vS@WND6x?60Z&pj)Zej0>kSK-_fQUY!lXLa5Pk$OPk+N|Gr-jy}c6 zCh{1kV#fa+IKbC2TdArjRFm3J{sdSJe(a-3d4YhbuHHW z?Yn$kTn=5_iU^-*9~l6Q2W7P{d%%sIe_NTJ;7Sdtd$5sYgK$8qygOF#raa5_?m%Eu zQVHd6e)dGE5+yWK?$@p4(Fm%ceOHZaaPo(%wba-TKZb@XQYeWs@J@hlmbd_5}4G#P|C0ovB=gy1}sE=doBngMVf ztuguCYO>ny5xu7d=mKc6)>F@a)@+dFK{hox!^uJ6db4R|+1ZDou0VOemXa52GT9`2 z+^tOZt)$-M46hct({>3i8CMu(v-QKRAa=%~|&<*X7Neb1= zQFMbZg_SwJ5#y(@>Zj4iDR^&>bV8NP^xB2ljolH_mT2)0aK%$6c(ePkOEYmiveV^; z?0Iw-8u*;xqYe>uN)k_Do7Xldc40+Ep+$o(%ap-J9%@3=lm74j)Er1ZFIO!%lNuw} TbM;ZD^!M!Ezl-{9@R|Pu7^{|R literal 19022 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 Yp*ru#sc*?;$TvSYx$L3s_CNi90cn5gT>t<8 diff --git a/docs/reference/kde1d-package.html b/docs/reference/kde1d-package.html index fea3010..6f12b05 100644 --- a/docs/reference/kde1d-package.html +++ b/docs/reference/kde1d-package.html @@ -72,7 +72,7 @@ kde1d - 1.0.0 + 1.0.1 @@ -158,7 +158,7 @@

    Contents

    -

    Site built with pkgdown 1.4.1.9000.

    +

    Site built with pkgdown 1.4.1.

    diff --git a/docs/reference/kde1d.html b/docs/reference/kde1d.html index 438af5c..f0ec6d4 100644 --- a/docs/reference/kde1d.html +++ b/docs/reference/kde1d.html @@ -70,7 +70,7 @@ kde1d - 1.0.0 + 1.0.1 @@ -179,7 +179,7 @@

    Details log-transform is used if there is only one boundary (see, Geenens and Wang, 2018); a probit transform is used if there are two (see, Geenens, 2014).

    Discrete variables are handled via jittering (see, Nagler, 2018a, 2018b). -A specific form of deterministic jittering is used, see equi_jitter().

    +A specific form of deterministic jittering is used, see equi_jitter().

    References

    Geenens, G. (2014). Probit transformation for kernel density @@ -201,15 +201,15 @@

    R Statistical Society, Series B, 53, 683–690.

    See also

    - +

    dkde1d(), pkde1d(), qkde1d(), rkde1d(), +plot.kde1d(), lines.kde1d()

    Examples

    ## unbounded data x <- rnorm(500) # simulate data fit <- kde1d(x) # estimate density -dkde1d(0, fit) # evaluate density estimate +dkde1d(0, fit) # evaluate density estimate summary(fit) # information about the estimate
    #> kernel density estimate ('kde1d'), log-quadratic #> ----------------------------------------------------------------- #> nobs = 500, bw = 0.71, loglik = -712.05, d.f. = 4.65
    plot(fit) # plot the density estimate
    curve(dnorm(x), @@ -219,10 +219,10 @@

    Examp ## bounded data, log-linear x <- rgamma(500, shape = 1) # simulate data fit <- kde1d(x, xmin = 0, deg = 1) # estimate density -dkde1d(seq(0, 5, by = 1), fit) # evaluate density estimate +dkde1d(seq(0, 5, by = 1), fit) # evaluate density estimate summary(fit) # information about the estimate

    #> kernel density estimate ('kde1d'), log-linear with bounded support (xmin = 0) #> ----------------------------------------------------------------- -#> nobs = 500, bw = 0.3, loglik = -449.06, d.f. = 12.9
    plot(fit) # plot the density estimate
    curve(dgamma(x, shape = 1), # add true density +#> nobs = 500, bw = 0.3, loglik = -450.93, d.f. = 12.89
    plot(fit) # plot the density estimate
    curve(dgamma(x, shape = 1), # add true density add = TRUE, col = "red", from = 1e-3 )
    @@ -230,7 +230,7 @@

    Examp x <- rbinom(500, size = 5, prob = 0.5) # simulate data x <- ordered(x, levels = 0:5) # declare as ordered fit <- kde1d(x) # estimate density -dkde1d(sort(unique(x)), fit) # evaluate density estimate +dkde1d(sort(unique(x)), fit) # evaluate density estimate summary(fit) # information about the estimate

    #> (jittered) kernel density estimate ('kde1d'), log-quadratic #> ----------------------------------------------------------------- #> nobs = 500, bw = 1.12, loglik = -789.98, d.f. = 10.08
    plot(fit) # plot the density estimate
    points(ordered(0:5, 0:5), # add true density @@ -264,7 +264,7 @@

    Contents

    -

    Site built with pkgdown 1.4.1.9000.

    +

    Site built with pkgdown 1.4.1.

    diff --git a/docs/reference/plot.kde1d.html b/docs/reference/plot.kde1d.html index d083bb4..e79632b 100644 --- a/docs/reference/plot.kde1d.html +++ b/docs/reference/plot.kde1d.html @@ -69,7 +69,7 @@ kde1d - 1.0.0 + 1.0.1 @@ -138,20 +138,20 @@

    Arg

    See also

    - +

    kde1d()

    Examples

    ## continuous data x <- rbeta(100, shape1 = 0.3, shape2 = 0.4) # simulate data -fit <- kde1d(x) # unbounded estimate +fit <- kde1d(x) # unbounded estimate plot(fit, ylim = c(0, 4)) # plot estimate
    curve(dbeta(x, 0.3, 0.4), # add true density col = "red", add = TRUE -)
    fit_bounded <- kde1d(x, xmin = 0, xmax = 1) # bounded estimate +)
    fit_bounded <- kde1d(x, xmin = 0, xmax = 1) # bounded estimate lines(fit_bounded, col = "green")
    ## discrete data x <- rpois(100, 3) # simulate data x <- ordered(x, levels = 0:20) # declare variable as ordered -fit <- kde1d(x) # estimate density +fit <- kde1d(x) # estimate density plot(fit, ylim = c(0, 0.25)) # plot density estimate
    points(ordered(0:20, 0:20), # add true density values dpois(0:20, 3), col = "red" @@ -175,7 +175,7 @@

    Contents

    -

    Site built with pkgdown 1.4.1.9000.

    +

    Site built with pkgdown 1.4.1.

    diff --git a/inst/include/kde1d/dpik.hpp b/inst/include/kde1d/dpik.hpp index 2dad465..d62586d 100644 --- a/inst/include/kde1d/dpik.hpp +++ b/inst/include/kde1d/dpik.hpp @@ -161,6 +161,9 @@ PluginBandwidthSelector::select_bw(size_t deg) } catch (...) { bw = 4.0 * 1.06 * scale_ * std::pow(n, -1.0 / (bwpow + 1)); } + if (std::isnan(bw)) { + bw = 4.0 * 1.06 * scale_ * std::pow(n, -1.0 / (bwpow + 1)); + } return bw; } diff --git a/inst/include/kde1d/interpolation.hpp b/inst/include/kde1d/interpolation.hpp index 7809f69..6c8cb84 100644 --- a/inst/include/kde1d/interpolation.hpp +++ b/inst/include/kde1d/interpolation.hpp @@ -1,8 +1,8 @@ #pragma once +#include "tools.hpp" #include #include -#include "tools.hpp" namespace kde1d { @@ -28,15 +28,13 @@ class InterpolationGrid1d Eigen::VectorXd integrate(const Eigen::VectorXd& u, bool normalize = false) const; - Eigen::VectorXd get_values() const {return values_;} - Eigen::VectorXd get_grid_points() const {return grid_points_;} + Eigen::VectorXd get_values() const { return values_; } + Eigen::VectorXd get_grid_points() const { return grid_points_; } private: // Utility functions for spline Interpolation - double cubic_poly(const double& x, - const Eigen::VectorXd& a) const; - double cubic_indef_integral(const double& x, - const Eigen::VectorXd& a) const; + double cubic_poly(const double& x, const Eigen::VectorXd& a) const; + double cubic_indef_integral(const double& x, const Eigen::VectorXd& a) const; double cubic_integral(const double& lower, const double& upper, const Eigen::VectorXd& a) const; @@ -47,7 +45,6 @@ class InterpolationGrid1d Eigen::MatrixXd values_; }; - //! Constructor //! //! @param grid_points an ascending sequence of grid points. @@ -69,7 +66,8 @@ inline InterpolationGrid1d::InterpolationGrid1d( //! renormalizes the estimate to integrate to one //! //! @param times how many times the normalization routine should run. -inline void InterpolationGrid1d::normalize(int times) +inline void +InterpolationGrid1d::normalize(int times) { double x_max = grid_points_(grid_points_.size() - 1); double int_max; @@ -81,16 +79,14 @@ inline void InterpolationGrid1d::normalize(int times) //! Interpolation //! @param x vector of evaluation points. -inline Eigen::VectorXd InterpolationGrid1d::interpolate( - const Eigen::VectorXd& x) const +inline Eigen::VectorXd +InterpolationGrid1d::interpolate(const Eigen::VectorXd& x) const { Eigen::VectorXd tmp_coefs(4); - ptrdiff_t m = grid_points_.size(); - - auto interpolate_one = [&] (const double& xx) { + auto interpolate_one = [&](const double& xx) { int k = find_cell(xx); - double xev = (xx - grid_points_(k)) / - (grid_points_(k + 1) - grid_points_(k)); + double xev = + (xx - grid_points_(k)) / (grid_points_(k + 1) - grid_points_(k)); // use Gaussian tail for extrapolation if (xev <= 0) { @@ -109,8 +105,8 @@ inline Eigen::VectorXd InterpolationGrid1d::interpolate( //! //! @param x a vector of evaluation points //! @param normalize whether to normalize the integral to a maximum value of 1. -inline Eigen::VectorXd InterpolationGrid1d::integrate(const Eigen::VectorXd& x, - bool normalize) const +inline Eigen::VectorXd +InterpolationGrid1d::integrate(const Eigen::VectorXd& x, bool normalize) const { Eigen::VectorXd res(x.size()); auto ord = tools::get_order(x); @@ -147,7 +143,7 @@ inline Eigen::VectorXd InterpolationGrid1d::integrate(const Eigen::VectorXd& x, } // integrate over partial cell - if (upr < grid_points_(m - 1)) { // only if still in interior + if (upr < grid_points_(m - 1)) { // only if still in interior tmp_coefs = find_cell_coefs(k); tmp_eps = (grid_points_(k + 1) - grid_points_(k)); upr = (upr - grid_points_(k)) / tmp_eps; @@ -178,8 +174,8 @@ inline Eigen::VectorXd InterpolationGrid1d::integrate(const Eigen::VectorXd& x, //! //! @param x evaluation point. //! @param a polynomial coefficients -inline double InterpolationGrid1d::cubic_poly(const double& x, - const Eigen::VectorXd& a) const +inline double +InterpolationGrid1d::cubic_poly(const double& x, const Eigen::VectorXd& a) const { double x2 = x * x; double x3 = x2 * x; @@ -190,8 +186,9 @@ inline double InterpolationGrid1d::cubic_poly(const double& x, //! //! @param x evaluation point. //! @param a polynomial coefficients. -inline double InterpolationGrid1d::cubic_indef_integral( - const double& x, const Eigen::VectorXd& a) const +inline double +InterpolationGrid1d::cubic_indef_integral(const double& x, + const Eigen::VectorXd& a) const { double x2 = x * x; double x3 = x2 * x; @@ -204,16 +201,16 @@ inline double InterpolationGrid1d::cubic_indef_integral( //! @param lower lower limit of the integral. //! @param upper upper limit of the integral. //! @param a polynomial coefficients. -inline double InterpolationGrid1d::cubic_integral(const double& lower, - const double& upper, - const Eigen::VectorXd& a) - const +inline double +InterpolationGrid1d::cubic_integral(const double& lower, + const double& upper, + const Eigen::VectorXd& a) const { return cubic_indef_integral(upper, a) - cubic_indef_integral(lower, a); } - -inline int InterpolationGrid1d::find_cell(const double& x0) const +inline int +InterpolationGrid1d::find_cell(const double& x0) const { int low = 0, high = grid_points_.size() - 1; int mid; @@ -231,7 +228,8 @@ inline int InterpolationGrid1d::find_cell(const double& x0) const //! Calculate coefficients for cubic intrpolation spline //! //! @param k the cell index. -inline Eigen::VectorXd InterpolationGrid1d::find_cell_coefs(const int& k) const +inline Eigen::VectorXd +InterpolationGrid1d::find_cell_coefs(const int& k) const { // indices for cell and neighboring grid points int k0 = std::max(k - 1, 0); @@ -262,7 +260,7 @@ inline Eigen::VectorXd InterpolationGrid1d::find_cell_coefs(const int& k) const // ensure positivity (Schmidt and Hess, DOI:10.1007/bf01934097) dx1 = std::max(dx1, -3 * values_(k)); - dx2 = std::min(dx2, 3 * values_(k2)); + dx2 = std::min(dx2, 3 * values_(k2)); // compute coefficents Eigen::VectorXd a(4); diff --git a/inst/include/kde1d/kde1d.hpp b/inst/include/kde1d/kde1d.hpp index abbcd05..8bce809 100644 --- a/inst/include/kde1d/kde1d.hpp +++ b/inst/include/kde1d/kde1d.hpp @@ -129,7 +129,7 @@ inline Kde1d::Kde1d(const Eigen::VectorXd& x, Eigen::VectorXd w = weights; tools::remove_nans(xx, w); if (w.size() > 0) - w /= w.sum(); + w /= w.mean(); if (nlevels_ > 0) xx = stats::equi_jitter(xx); xx = boundary_transform(xx); @@ -155,7 +155,6 @@ inline Kde1d::Kde1d(const Eigen::VectorXd& x, loglik_ = grid_.interpolate(x).cwiseMax(1e-20).array().log().sum(); // calculate effective degrees of freedom - double n = x.size(); interp::InterpolationGrid1d infl_grid( grid_points, fitted.col(1).cwiseMin(2.0).cwiseMax(0), 0); edf_ = infl_grid.interpolate(x).sum(); @@ -353,7 +352,7 @@ Kde1d::fit_lp(const Eigen::VectorXd& x, grid_points(0), grid_points(m - 1), m - 1, - wbin); + Eigen::VectorXd::Ones(x.size())); wbin = wcount.cwiseQuotient(count); } @@ -411,7 +410,7 @@ Kde1d::calculate_infl(const size_t& n, M(1, 0) = M(0, 1); M(1, 1) = f0 * bw2 + f0 * bw2 * bw2 * b2; M_inverse00 = M.inverse()(0, 0); - } else if (deg_ == 2) { + } else { Eigen::Matrix3d M; M(0, 0) = f0; M(0, 1) = f0 * b; @@ -457,7 +456,7 @@ Kde1d::boundary_transform(const Eigen::VectorXd& x, bool inverse) // two boundaries -> probit transform auto rng = xmax_ - xmin_; x_new = stats::pnorm(x).array() + xmin_ - 5e-5 * rng; - x_new *= (xmax_ - xmin_ + 1e-4 * rng); + x_new *= (xmax_ - xmin_ + 1e-4 * rng); } else if (!std::isnan(xmin_)) { // left boundary -> log transform x_new = x.array().exp() + xmin_ - 1e-5; @@ -499,7 +498,11 @@ Kde1d::boundary_correct(const Eigen::VectorXd& x, const Eigen::VectorXd& fhat) corr_term.fill(1.0); } - return fhat.array() * corr_term.array(); + Eigen::VectorXd f_corr = fhat.cwiseProduct(corr_term); + if (std::isnan(xmin_) & !std::isnan(xmax_)) + f_corr.reverseInPlace(); + + return f_corr; } //! constructs a grid later used for interpolation @@ -510,12 +513,10 @@ Kde1d::construct_grid_points(const Eigen::VectorXd& x) { Eigen::VectorXd rng(2); rng << x.minCoeff(), x.maxCoeff(); - if (std::isnan(xmin_) && std::isnan(xmax_)) - rng(0) -= 4 * bw_; - if (std::isnan(xmax_)) - rng(1) += 4 * bw_; - if (std::isnan(xmin_) && !std::isnan(xmax_)) - std::swap(rng(0), rng(1)); + if (std::isnan(xmin_) && std::isnan(xmax_)) { + rng(0) -= 4 * bw_; + rng(1) += 4 * bw_; + } auto zgrid = Eigen::VectorXd::LinSpaced(401, rng(0), rng(1)); return boundary_transform(zgrid, true); } @@ -525,6 +526,8 @@ Kde1d::construct_grid_points(const Eigen::VectorXd& x) inline Eigen::VectorXd Kde1d::finalize_grid(Eigen::VectorXd& grid_points) { + if (std::isnan(xmin_) & !std::isnan(xmax_)) + grid_points.reverseInPlace(); if (!std::isnan(xmin_)) grid_points(0) = xmin_; if (!std::isnan(xmax_)) @@ -533,7 +536,6 @@ Kde1d::finalize_grid(Eigen::VectorXd& grid_points) return grid_points; } - // Bandwidth for Kernel Density Estimation //' @param x vector of observations //' @param bw bandwidth parameter, NA for automatic selection. diff --git a/inst/include/kde1d/kdefft.hpp b/inst/include/kde1d/kdefft.hpp index ca712e0..997d4ac 100644 --- a/inst/include/kde1d/kdefft.hpp +++ b/inst/include/kde1d/kdefft.hpp @@ -1,7 +1,7 @@ #pragma once -#include "tools.hpp" #include "stats.hpp" +#include "tools.hpp" #include namespace kde1d { @@ -30,7 +30,7 @@ class KdeFFT Eigen::VectorXd bin_counts_; double lower_; double upper_; - size_t num_bins_{ 400 }; + static constexpr size_t num_bins_{ 400 }; }; //! @param x vector of observations. @@ -43,9 +43,9 @@ inline KdeFFT::KdeFFT(const Eigen::VectorXd& x, double lower, double upper, const Eigen::VectorXd& weights) - : bw_(bw) - , lower_(lower) - , upper_(upper) + : bw_(bw) + , lower_(lower) + , upper_(upper) { if (weights.size() > 0 && (weights.size() != x.size())) throw std::runtime_error("x and weights must have the same size"); @@ -59,7 +59,6 @@ inline KdeFFT::KdeFFT(const Eigen::VectorXd& x, bin_counts_ = tools::linbin(x, lower_, upper_, num_bins_, w); } - //! Binned kernel density derivative estimate //! @param drv order of derivative. //! @return estimated derivative evaluated at the bin centers. diff --git a/inst/include/kde1d/stats.hpp b/inst/include/kde1d/stats.hpp index af16768..16dc113 100644 --- a/inst/include/kde1d/stats.hpp +++ b/inst/include/kde1d/stats.hpp @@ -1,13 +1,13 @@ #pragma once #define BOOST_MATH_PROMOTE_DOUBLE_POLICY false +#include "tools.hpp" #include #include #include #include #include #include -#include "tools.hpp" namespace kde1d { @@ -120,7 +120,6 @@ quantile(const Eigen::VectorXd& x, auto x2 = x; auto wcum = w; - auto wrank = Eigen::VectorXd::Constant(n, 0.0); double wacc = 0.0; for (size_t i = 0; i < n; ++i) { x2(i) = x(ind[i]); diff --git a/inst/include/kde1d/tools.hpp b/inst/include/kde1d/tools.hpp index d1d441f..00fd3a3 100644 --- a/inst/include/kde1d/tools.hpp +++ b/inst/include/kde1d/tools.hpp @@ -10,7 +10,8 @@ namespace tools { //! @param x function argument. //! @param func function to be applied. template -Eigen::MatrixXd unaryExpr_or_nan(const Eigen::MatrixXd &x, const T& func) +Eigen::MatrixXd +unaryExpr_or_nan(const Eigen::MatrixXd& x, const T& func) { return x.unaryExpr([&func](double y) { if (std::isnan(y)) { @@ -31,12 +32,12 @@ Eigen::MatrixXd unaryExpr_or_nan(const Eigen::MatrixXd &x, const T& func) //! @param n_iter the number of iterations for the bisection. //! //! @return \f$ f^{-1}(x) \f$. -inline Eigen::VectorXd invert_f( - const Eigen::VectorXd &x, - std::function f, - const double lb, - const double ub, - int n_iter) +inline Eigen::VectorXd +invert_f(const Eigen::VectorXd& x, + std::function f, + const double lb, + const double ub, + int n_iter) { Eigen::VectorXd xl = Eigen::VectorXd::Constant(x.size(), lb); Eigen::VectorXd xh = Eigen::VectorXd::Constant(x.size(), ub); @@ -51,12 +52,12 @@ inline Eigen::VectorXd invert_f( return x_tmp; } - //! remove rows of a matrix which contain nan values or have zero weight //! @param x the matrix. //! @param a vector of weights that is either empty or whose size is equal to //! the number of columns of x. -inline void remove_nans(Eigen::VectorXd& x, Eigen::VectorXd& weights) +inline void +remove_nans(Eigen::VectorXd& x, Eigen::VectorXd& weights) { if ((weights.size() > 0) & (weights.size() != x.rows())) throw std::runtime_error("sizes of x and weights don't match."); @@ -82,8 +83,8 @@ inline void remove_nans(Eigen::VectorXd& x, Eigen::VectorXd& weights) weights.conservativeResize(last + 1); } -inline Eigen::Matrix get_order( - const Eigen::VectorXd& x) +inline Eigen::Matrix +get_order(const Eigen::VectorXd& x) { Eigen::Matrix order(x.size()); for (size_t i = 0; i < x.size(); ++i) @@ -91,27 +92,31 @@ inline Eigen::Matrix get_order( std::stable_sort( order.data(), order.data() + order.size(), - [&] (const size_t& a, const size_t& b) { return (x[a] < x[b]); } - ); + [&](const size_t& a, const size_t& b) { return (x[a] < x[b]); }); return order; } //! Computes bin counts for univariate data via the linear binning strategy. //! @param x vector of observations //! @param weights vector of weights for each observation. -inline Eigen::VectorXd linbin(const Eigen::VectorXd& x, - double lower, - double upper, - size_t num_bins, - const Eigen::VectorXd& weights) +inline Eigen::VectorXd +linbin(const Eigen::VectorXd& x, + double lower, + double upper, + size_t num_bins, + const Eigen::VectorXd& weights) { Eigen::VectorXd gcnts = Eigen::VectorXd::Zero(num_bins + 1); double rem, lxi, delta; + size_t li; + + if (upper <= lower) + throw std::runtime_error("upper != lower"); delta = (upper - lower) / num_bins; for (size_t i = 0; i < x.size(); ++i) { lxi = (x(i) - lower) / delta; - size_t li = static_cast(lxi); + li = static_cast(lxi); rem = lxi - li; if (li < num_bins) { gcnts(li) += (1 - rem) * weights(i); diff --git a/man/dkde1d.Rd b/man/dkde1d.Rd index 187f7bf..2b5e6ed 100644 --- a/man/dkde1d.Rd +++ b/man/dkde1d.Rd @@ -30,7 +30,7 @@ rkde1d(n, obj, quasi = FALSE) \item{quasi}{logical; the default (\code{FALSE}) returns pseudo-random numbers, use \code{TRUE} for quasi-random numbers (generalized Halton, see -\code{\link[qrng:ghalton]{qrng::ghalton()}}).} +\code{\link[randtoolbox:sobol]{randtoolbox::sobol()}}).} } \value{ The density, distribution function or quantile functions estimates