*! version 0.1 June 15 2010

*! version 0.2 July 12 2010

*! version 0.3 July 25 2010

*! version 0.4 Mar 7, 2012

*! version 0.5 Mar 20, 2012

*! version 0.6 Sep 25, 2013
help rds, help rds_network (SJ12-1: st0247)

Title

rds -- Respondent-driven sampling

Syntax

rds
varname
[if] [in],
id(varname)
degree(varname)
recruiter_id(varname)
recruiter_var(varname)
[rds_options]

rds_network
varname,
id(varname)
coupon(str)
ncoupon(#)
degree(varname)
[rds_network_options]

rds_options

* id(varname) unique coupon code of respondent R

* degree(varname) network size

* recruiter_id(varname) variable with ID of R's recruiter

* recruiter_var(varname) variable with analysis variable of R's recruiter

wgt(newvar) create variable with individualized weight

wgt_pop(newvar) create variable with population weight

detail show detailed convergence output

convtol(#) set convergence tolerance

network_size_method(str) set method to compute average group degree

* id(), degree(), recruiter_id(), and
recruiter_var() are required.

rds_network_options

* id(varname) unique coupon code of respondent R

* coupon(str) stem of variable names containing R's coupons

* ncoupon(#) number of coupons

* degree(varname) network size

ancestor(newvar) create variable with ID of seed from which R was recruited

depth(newvar) create variable with R's referral depth

recruiter_id(newvar) create variable with ID of R's recruiter

recruiter_var(newvar) create variable with analysis variable of R's recruiter

* id(), coupon(), ncoupon(), and degree() are required.

Description

Respondent-driven sampling is a technique to sample networked
populations. It shares some similarities with snowball sampling but
also requires estimates of network size (degree) and information about
who recruited whom. Importantly, Markov chain theory makes it possible
to compute sampling probabilities.

rds_network computes information about respondents'
recruiters that is required as input for rds. rds estimates
population proportions, weights, and other statistics.

This program implements Heckathorn's original estimator as well
as the Volz-Heckathorn estimator.

For those familiar with the standalone software "RDS Analysis
Tool" (RDSAT) by Heckathorn and Wejnert
(downloadable from
http://www.respondentdrivensampling.org), differences include the following: 1)
RDSAT distinguishes between an ID and a coupon for the respondent.
Because coupons should already be unique, rds_network uses only
the coupon of the respondent as the identifying variable. Because seeds
respondents do not have coupons, they must be given different unique
values. 2) Missing values are coded as ".", as is customary in Stata
(Heckathorn's software typically uses "0").

Options for both commands

id(varname) specifies the coupon code of the respondent.
This variable is also used as a unique respondent identifier. For
seeds, any (nonmissing) unique value can be used. Each different seed
must have a different value for varname. This variable must be
numeric -- string ID variables should be converted to numeric variables
first; see example 7.

degree(varname) specifies the variable containing
the respondent's network size. Values must be greater than zero. If the data
contain zeros, the recommended procedure is to replace them with
missing values.

Options unique to rds

recruiter_id(varname) specifies a variable containing the ID
of the recruiter and missing values for seeds who do not have a
recruiter, if specified in rds_network. This variable is needed
as input to rds. recruiter_id() is required.

recruiter_var(varname) specifies a variable containing the
recruiter's analysis variable, if the recruited's analysis variable is
specified in varlist. This variable is needed as input to
rds. recruiter_var() is required.

wgt(newvar) creates a variable containing individual
sampling weights. To the extent that degrees for individuals are missing,
group degree is used. This option should not be used in conjunction
with bootstrapping because bootstrapping is not possible when a new
variable is created.

wgt_pop(newvar) creates a variable containing
population sampling weights. This option should not be used in
conjunction with bootstrapping because bootstrapping is not possible
when a new variable is created.

detail shows detailed output for individual iterations when
computing the number of iterations needed for convergence to the
equilibrium. Starting with a sample where all members belong to a
single category, the corresponding column of the output matrix displays
the simulated sample distribution after i iterations (waves). The
sample distribution corresponding to the jth category is shown in the
jth column of the output matrix.

convtol(#) specifies the convergence tolerance, a number
between 0 and 1. The default is convtol(0.02). Convergence to the
equilibrium is reached if the difference of two successive simulated
distributions of recruits is less than convtol() for all groups.

network_size_method(str) specifies the method as
multiplicity (the default) or average.
network_size_method(multiplicity) takes into account that people with
larger networks are more likely to be sampled;
network_size_method(average) computes the average network size of all
respondents. The default should not be changed without good reason.

Options unique to rds_network

coupon(str) specifies the stem of the variable names for referral
coupons. Variable names are str1 through
str#, where # is the number of referral coupons. For example, if coupon equals ref and
there are three referral coupons, the coupons are contained in variables
with the names ref1, ref2, and ref3. The program
verifies that referral coupons are unique. Missing values for coupons
are allowed. Referral coupons must be numeric -- string referral coupons
should be converted to numeric variables first.

ncoupon(#) specifies the number of referral coupons.

ancestor(newvar) creates a variable containing the ID
of the seed to which a recruit can be traced back.

depth(newvar) creates a variable containing the depth
of the referral chain. Seeds have depth 0, their recruits have depth 1,
and so forth.

recruiter_id(newvar) creates a variable containing the ID
of the recruiter and missing values for seeds who do not have a
recruiter, if specified in rds_network. This variable is needed
as input to rds.

recruiter_var(newvar) creates a variable containing the
recruiter's analysis variable, if the recruited's analysis variable is
specified in varlist. This variable is needed as input to
rds.

Remarks

RDS methodology requires that continuous variables are broken up
into categories. Therefore, varname should be categorical.
varname must not contain missing values. Missing values should be
imputed beforehand.

Examples

Example 1. Create a new variable, wgt, with weights based on the
transition matrix for race. There are three referral coupons in the
variables ref1, ref2, and ref3. degree() specifies the
network size of each respondent.

. rds_network race, id(coupon) coupon(ref) ncoupon(3) degree(degree) recruiter_var(r_var) recruiter_id(r_id)

. rds race, id(coupon) wgt(wgt) degree(degree) recruiter_var(r_var) recruiter_id(r_id)

Example 2. Bootstrap estimated population proportions to
construct bootstrap confidence intervals. To preserve the network
structure, first create recruiter_id() and recruiter_var():

. rds_network race, id(id) coupon(ref) ncoupon(3) degree(degree) recruiter_id(p_id) recruiter_var(p_var)

Specifically for bootstrapping, the population proportion P is
also saved in _b. _b can be bootstrapped as a vector:

. set seed 1

. bootstrap _b, reps(1000) notable: rds race, id(id) degree(degree) recruiter_id(p_id) recruiter_var(p_var)

Using the percentile option (rather than the normality
assumption) guarantees that the confidence limits are not outside the
interval [0,1]:

. estat bootstrap, percentile

Example 3. Create an analysis variable from unique
combinations of race and gender.

. egen myvar = group(race gender)

. rds_network myvar, id(coupon) coupon(ref) ncoupon(3) degree(degree) recruiter_id(r_id) recruiter_var(r_var)

. rds myvar, id(coupon) wgt(wgt) degree(degree) recruiter_id(r_id) recruiter_var(r_var)

Example 4. Use a continuous variable as an analysis
variable. First break the continuous variable (for example, income)
into categories.

. egen myvar = cut(income), group(4)

. rds_network myvar, id(coupon) coupon(ref) ncoupon(3) degree(degree) recruiter_id(r_id) recruiter_var(r_var)

. rds myvar, id(coupon) wgt(wgt) degree(degree) recruiter_id(r_id) recruiter_var(r_var)

Example 5. Analyze respondents only from wave 3 onward
(including wave 2 recruiter information):

. rds_network race, id(coupon) coupon(ref) ncoupon(3) degree(degree) recruiter_id(r_id) recruiter_var(r_var) depth(wave)

. rds race if wave>=3, id(coupon) wgt(wgt) degree(degree) recruiter_id(r_id) recruiter_var(r_var)

Example 6. Using data on psychiatric diagnoses in an RDS
sample of injection drug users, estimate the proportions of
male and female injection drug users with a diagnosis. Run a 2x2
partition with sex and diagnosis, providing the four proportions. Get the confidence intervals for the proportion of males with
a positive diagnosis and the proportion of females with a positive
diagnosis -- for example, male_positive/(male_negative + male_positive).

. bootstrap p1=(_b[P2]/(_b[P1]+_b[P2])): rds [...]

Note: P1 and P2 are the column names of the (original) estimator stored in e(b) and correspond to the first two groups.
If using the Volz-Heckathorn estimator instead, substitute P1 and P2 with VH1 and VH2.

[Example 6 and its solution were contributed by Mary E. Mackesy-Amiti.]

Example 7. Referral codes must be numeric. Conversion to numeric can
accomplished, for example, using Nick Cox's multencode command. This
command ensures that the encoding scheme used is the same for all variables.

. multencode code friend_code_1 friend_code_2 friend_code_3
friend_code_4, generate(id ref1 ref2 ref3 ref4)

. rds_network myvar, id(id) coupon("ref") ncoupon(4) degree(u2)

Saved results

rds saves the following in e():

Scalars

e(n_group) number of groups of varname

Matrices

e(b) vector of population proportions (for bootstrapping)

e(SampleP) vector of sample proportions

e(W) vector of weights

e(P) vector of population proportions

e(VH) vector of Volz-Heckathorn estimate of population proportions

e(GROUPSIZE) vector of sample sizes

e(DEGREE) vector of degree (network size)

e(E) vector of equilibrium probabilities

e(CATEGORIES) vector of categories of varname

e(H) homophily vector

e(obs) number of observations in transition matrix

e(T1) transition matrix (before smoothing)

e(R) demographically adjusted matrix

e(smoothR) smoothed number of observations in transition matrix

e(T) transition matrix

Acknowledgment

This program was developed during a sabbatical with the
Socio-Economic Panel at the German Institute for Economic Research (DIW).

Author

Matthias Schonlau

DIW Berlin (German Institute for Economic Research)

Berlin, Germany

University of Waterloo

Waterloo, Canada

schonlau@uwaterloo.ca

http://www.schonlau.net

Also see

http://www.respondentdrivensampling.org

To get identical results, set options in the RDSAT software as
follows: Average network size: multiplicity, Algorithm: Data Smoothing,
1-tailed alpha: 0.025.

Article: Stata Journal, volume 12, number 1: st0247