Fit Two-Component Normal and Lognormal Mixture Models
Overview
Fits, bootstraps, and evaluates two-component normal and lognormal mixture models. Parameters are searched within data-derived bounds by differential-evolution global optimization, as implemented in the 'DEoptim' package (Mullen, Ardia, Gil, Windover and Cline, 2011) doi:10.18637/jss.v040.i06, followed by a local 'L-BFGS-B' refinement step via optim(). Also provides preliminary diagnostic plots, diagnostic plots for fitted mixtures, automatic normal-versus-lognormal model selection by the Bayesian or Akaike information criterion, and parametric or nonparametric bootstrap confidence intervals for the fitted parameters.
This release corrects the numerical objective, checks optimizer convergence,
adds input validation, diagnostics and new plots. Several changes alter
numerical results; see "Changes that can alter results".
Changes that can alter results
- **Exact log-likelihood.** The objective is now evaluated by log-sum-exp. Version 0.2.0 computed
sum(log(density + 1e-12)), which capped the contribution of every observation whose mixture density was below 1e-12. The previous objective useddensity_floor = 1e-12; this option is no longer part of the public API. Log-likelihoods, AIC, BIC and, for data with extreme observations, the fitted parameters can differ from 0.2.0. Note that the floor acted as an implicit robustification: with the exact likelihood a single extreme observation can attract a component of its own. This is reported by the new diagnostics (see below).
Show all changes in 0.3.0Hide the rest of the changes in 0.3.0
- **L-BFGS-B convergence is checked.** A local refinement is accepted only if
optim()reports convergence code 0. Otherwise a warning is given and the unrefined DE solution is returned (fit$source == "DEoptim_nolocal").fit$convergenceandfit$messagenow describe the returned candidate (0.2.0 always reported the run started from the DE solution). - **Defaults of
n_runs.**fit_norm2(),fit_lognorm2()now default ton_runs = 10(was 20).select_best_mixture()now uses the same defaults as the fitting functions,n_runs = 10,NP = 100(was 1 and 50). - **Bootstrap.** Replicates are accepted only if the refinement converged; default bounds are recomputed from every bootstrap sample (as for the original fit);
centralis now the **median for both families** (0.2.0: mean for normal, median for lognormal; usecenter = "mean"); the mean and median are always returned. - **P-P plot.** The
"pp"panel ofprelim_plots()is now a proper normal P-P plot. In 0.2.0 it plotted the sorted empirical-CDF values against the observation index, which is the same straight line for any data set.
New features
mix2_bounds()(exported) returns the data-derived parameter bounds; the scale limits and the range of the mixing proportion are controlled withscale_rangeandp_range. The bounds are documented: the mean bounds are *not* split at the median.- Input validation:
xmust be finite (no NA/NaN/Inf) with at least 10 observations and non-zero variance; a warning is given for n < 50; user bounds must have length 5, be finite and ordered, and stay inside the model. - Fit objects store
source,local_convergence, the bounds (lower,upper),settings,de_logLik(log-likelihood of each DE run) anddiagnostics. Warnings andprint()/summary()notes flag solutions on a bound of the parameter box and components whose expected size (sum of posterior probabilities) is belowmin_comp_n(default 5). scale_ratioargument (default 0 = off): a Hathaway (1985)-type relative constraintmin(s1, s2) / max(s1, s2) >= scale_ratio, enforced by a quadratic penalty; the reported log-likelihood is the exact one. It is inherited bybootstrap_mix2()from the fit.bootstrap_mix2(refit = "de")repeats a differential-evolution search for every replicate (de_control);refit = "local"(default) is the fast local refit of 0.2.0 and is documented as not propagating multimodality. Failed replicates are counted (n_failed).plot(fit, which = "pit")andwhich = "qq"compare the data with the fitted mixture.prelim_plots()gains"logpp".select_best_mixture(criterion = "BIC" | "AIC"); errors of an individual family fit are reported instead of being swallowed.
Bug fixes and documentation
parallelType = 1requires theparallellypackage becauseDEoptimdoes; it is listed underSuggestsand a clear error is given if missing. The parallel objective is now self-contained for PSOCK workers, so internal DEmixR functions are not required on the worker search path. The numerical objective and the meanings ofparallelTypeare unchanged.DEoptimuses 0 = serial, 1 =parallel, and 2 =foreach.- In
bootstrap_mix2(),parallelTypeis the number of forked processes (values 0 and 1 run serially; ignored on Windows); the documentation of 0.2.0 described it as the DEoptim setting. - Documentation states that the search is bounded and that the result is not an unrestricted maximum-likelihood estimate; the lognormal
m/saremeanlog/sdlog; Q-Q/P-P panels are exploratory. - Test suite extended (validation, likelihood, boundary diagnostics, non-convergence handling, bootstrap failure handling, reproducibility).
From NEWS.md in the release
Install
Health
- OK13 OK2026-08-05
- NOTE12 OK, 1 NOTE2026-08-01
- OK14 OK2026-03-10
Documentation
- Help pages
- 14 (1 internal)
- Examples that run
- 69%9 run in a plain check · 4 only when donttest examples are enabled (R CMD check --as-cran)
- Exported functions with examples
- 100%
- Documented parameters
- 100%
- Return-value docs
- 100%
- Help pages citing references
- 7%
Downloads
Repository
3 development-tooling and community-health practices detected across 2 families in the upstream repository
Checks run against github.com/fhabibzadeh/demixr on 2026-10-25.
The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel
Dependencies
Code & Tests
People & History
Package metadata
- First published
- 2025-09-27
- Total releases
- 3 / 1 yrs
- License
- MIT + file LICENSE OSI
- Minimum R
- ≥ 4.0.0
- Download size
- 221 KB
Cite
Cite this package
Run in R for the authors' preferred citation:
citation("DEmixR")This package has no citation file, so citation() returns this entry built from DESCRIPTION.
The repository also keeps a CITATION.cff.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-26, which the citation names so these numbers can be found later. More on citing and the projects behind them.