nonprobsvy:
an R package for modern statistical inference methods based on
non-probability samples

The goal of this package is to provide R users access to modern methods for non-probability samples when auxiliary information from the population or probability sample is available:
The package allows for:
ncvreg, Rcpp, RcppArmadillo
packages),survey and srvyr
packages when probability sample is available (Lumley 2004, 2023; Freedman Ellis
and Schneider 2024),logit,
probit and cloglog) and outcome
(gaussian, binomial and poisson)
variables.Details on the use of the package can be found:
You can install the recent version of nonprobsvy package
from main branch Github with:
pak::pkg_install("ncn-foreigners/nonprobsvy")or install the stable version from CRAN
install.packages("nonprobsvy")or development version from the dev branch
pak::pkg_install("ncn-foreigners/nonprobsvy@dev")Consider the following setting where two samples are available: non-probability (denoted as \(S_{\text{NP}}\)) and probability (denoted as \(S_{\text{P}}\)) where a set of auxiliary variables (denoted as \(\boldsymbol{X}\)) is available for both sources, the target variable \(Y\) is observed in the non-probability sample, and design or calibrated weights (\(\boldsymbol{d}\) or \(\boldsymbol{w}\)) are observed in the probability sample.
| Sample | Auxiliary variables \(\boldsymbol{X}\) | Target variable \(Y\) | Design (\(\boldsymbol{d}\)) or calibrated (\(\boldsymbol{w}\)) weights | |
|---|---|---|---|---|
| \(S_{\text{NP}}\) (non-probability) | 1 | \(\checkmark\) | \(\checkmark\) | ? |
| … | \(\checkmark\) | \(\checkmark\) | ? | |
| \(n_{\text{NP}}\) | \(\checkmark\) | \(\checkmark\) | ? | |
| \(S_{\text{P}}\) (probability) | \(n_{\text{NP}}+1\) | \(\checkmark\) | ? | \(\checkmark\) |
| … | \(\checkmark\) | ? | \(\checkmark\) | |
| \(n_{\text{NP}}+n_{\text{P}}\) | \(\checkmark\) | ? | \(\checkmark\) |
The current implementation does not use target-variable values from
the probability sample. Data structures where \(Y\) is observed in both samples, or where
overlapping units must be linked across samples, are not currently
implemented. The dependence and key arguments
in control_sel() are reserved for future overlap handling
and currently raise a “not yet implemented” error if set.
Suppose \(Y\) is the target variable, \(\boldsymbol{X}\) is a matrix of auxiliary variables, \(R\) is the inclusion indicator. Then, if we are interested in estimating the mean \(\bar{\tau}_Y\) or the sum \(\tau_Y\) of the of the target variable given the observed data set \((y_k, \boldsymbol{x}_k, I_{\text{NP}, k})\), we can approach this problem with the possible scenarios:
Supported target-variable types depend on the estimator family:
| Estimator family | Supported target variable Y |
|---|---|
| IPW | Numeric targets whose population mean is meaningful, including continuous, count, and 0/1 binary variables. No outcome model is fitted. |
Mass imputation with method_outcome = "glm" |
Continuous, count, or binary variables through
family_outcome = "gaussian", "poisson", or
"binomial". |
Mass imputation with method_outcome = "nn",
"pmm", or "npar" |
Numeric targets; categorical, ordinal, survival, and other structured outcomes are not supported. |
| Doubly robust | GLM outcome models only; use
family_outcome = "gaussian", "poisson", or
"binomial". |
The compact examples below use the built-in admin
non-probability sample and jvs probability sample.
library(survey)
library(nonprobsvy)
data(admin)
data(jvs)
prob <- svydesign(
ids = ~1,
weights = ~weight,
strata = ~size + nace + region,
data = jvs
)
pop_totals <- colSums(model.matrix(~region + private + nace + size, jvs) * jvs$weight)| Estimator | Example code |
|---|---|
| Mass imputation based on regression imputation |
|
| Inverse probability weighting |
|
| Inverse probability weighting with calibration constraint |
|
| Doubly robust estimator |
|
| Estimator | Example code |
|---|---|
| Mass imputation based on regression imputation |
|
| Mass imputation based on nearest neighbour imputation |
|
| Mass imputation based on predictive mean matching |
|
| Mass imputation based on regression imputation with variable selection (LASSO) |
|
| Inverse probability weighting |
|
| Inverse probability weighting with calibration constraint |
|
| Inverse probability weighting with calibration constraint with variable selection (SCAD) |
|
| Doubly robust estimator |
|
| Doubly robust estimator with variable selection (SCAD) and bias minimization |
|
Simulate example data from the following paper: Kim, Jae Kwang, and Zhonglei Wang. “Sampling techniques for big data analysis.” International Statistical Review 87 (2019): S177-S191 [section 5.2]
library(survey)
library(nonprobsvy)
set.seed(1234567890)
N <- 1e6 ## 1000000
n <- 1000
x1 <- rnorm(n = N, mean = 1, sd = 1)
x2 <- rexp(n = N, rate = 1)
epsilon <- rnorm(n = N) # rnorm(N)
y1 <- 1 + x1 + x2 + epsilon
y2 <- 0.5*(x1 - 0.5)^2 + x2 + epsilon
p1 <- exp(x2)/(1+exp(x2))
p2 <- exp(-0.5+0.5*(x2-2)^2)/(1+exp(-0.5+0.5*(x2-2)^2))
flag_bd1 <- rbinom(n = N, size = 1, prob = p1)
flag_srs <- as.numeric(1:N %in% sample(1:N, size = n))
base_w_srs <- N/n
population <- data.frame(x1,x2,y1,y2,p1,p2,base_w_srs, flag_bd1, flag_srs, pop_size = N)
base_w_bd <- N/sum(population$flag_bd1)Declare svydesign object with survey
package
sample_prob <- svydesign(ids= ~1, weights = ~ base_w_srs,
data = subset(population, flag_srs == 1),
fpc = ~ pop_size)
sample_prob
#> Independent Sampling design
#> svydesign(ids = ~1, weights = ~base_w_srs, data = subset(population,
#> flag_srs == 1), fpc = ~pop_size)or with the srvyr package
sample_prob <- srvyr::as_survey_design(.data = subset(population, flag_srs == 1),
weights = base_w_srs)
sample_probIndependent Sampling design (with replacement)
Called via srvyr
Sampling variables:
Data variables:
- x1 (dbl), x2 (dbl), y1 (dbl), y2 (dbl), p1 (dbl), p2 (dbl), base_w_srs (dbl), flag_bd1 (int), flag_srs (dbl)Estimate population mean of y1 based on doubly robust
estimator using IPW with calibration constraints and we specify that
auxiliary variables should not be combined for the inference.
result_dr <- nonprob(
selection = ~ x2,
outcome = y1 + y2 ~ x1 + x2,
data = subset(population, flag_bd1 == 1),
svydesign = sample_prob
)Results
result_dr
#> A nonprob object
#> - estimator type: doubly robust
#> - method: glm (gaussian)
#> - IPW point estimator: Hajek (denominator: 1025063)
#> - auxiliary variables source: survey
#> - vars selection: false
#> - variance estimator: analytic
#> - population size fixed: false
#> - naive (uncorrected) estimators:
#> - variable y1: 3.1817
#> - variable y2: 1.8087
#> - selected estimators:
#> - variable y1: 2.9500 (se=0.0414, ci=(2.8689, 3.0312))
#> - variable y2: 1.5762 (se=0.0313, ci=(1.5150, 1.6375))Mass imputation estimator
result_mi <- nonprob(
outcome = y1 + y2 ~ x1 + x2,
data = subset(population, flag_bd1 == 1),
svydesign = sample_prob
)Results
result_mi
#> A nonprob object
#> - estimator type: mass imputation
#> - method: glm (gaussian)
#> - auxiliary variables source: survey
#> - vars selection: false
#> - variance estimator: analytic
#> - population size fixed: false
#> - naive (uncorrected) estimators:
#> - variable y1: 3.1817
#> - variable y2: 1.8087
#> - selected estimators:
#> - variable y1: 2.9498 (se=0.0420, ci=(2.8675, 3.0321))
#> - variable y2: 1.5760 (se=0.0326, ci=(1.5122, 1.6398))Inverse probability weighting estimator
For IPW, MLE without a fixed pop_size,
pop_totals, or pop_means uses the Hajek-type
estimator. Supplying a fixed population size uses the
Horvitz-Thompson-type estimator, while IPW-GEE with a reference survey
uses sum(weights(svydesign)) as the denominator.
result_ipw <- nonprob(
selection = ~ x2,
target = ~y1+y2,
data = subset(population, flag_bd1 == 1),
svydesign = sample_prob)Results
result_ipw
#> A nonprob object
#> - estimator type: IPW (Hajek, denominator: 1025063)
#> - method: logit (mle)
#> - auxiliary variables source: survey
#> - vars selection: false
#> - variance estimator: analytic
#> - population size fixed: false
#> - naive (uncorrected) estimators:
#> - variable y1: 3.1817
#> - variable y2: 1.8087
#> - selected estimators:
#> - variable y1: 2.9248 (se=0.0500, ci=(2.8269, 3.0227))
#> - variable y2: 1.5517 (se=0.0499, ci=(1.4539, 1.6496))Work on this package is supported by the National Science Centre, OPUS 20 grant no. 2020/39/B/HS4/00941.