This vignette shows the basic usage of the persuasio
package for estimation and inference on average persuasion rates (APR)
and local persuasion rates (LPR) in the potential-outcomes framework of
Jun and Lee (2023).
The package is designed for settings with a two-stage causal structure:
\[Z \text{ (instrument)} \rightarrow T \text{ (exposure)} \rightarrow Y \text{ (outcome)}\]
where \(Z\) is a binary instrument, such as random assignment or policy eligibility; \(T\) is actual exposure to a persuasive message, such as media consumption or campaign contact; and \(Y\) is a binary behavioral outcome, such as voting, donating, or purchasing. For an overview of empirical settings that motivate persuasion estimands, see DellaVigna and Gentzkow (2010, Annual Review of Economics, doi:10.1146/annurev.economics.102308.124309).
persuasio applicable?The framework applies whenever the empirical setting features:
The richest case uses individual-level data on \((Y, T, Z)\). Some estimands can also be computed when only \((Y, Z)\) are observed, or when only summary statistics are available.
persuasio TL;DRpersuasio is the recommended function for all estimation
and inference. The lower-level functions (aprlb,
aprub, lpr4ytz, and
calc4persuasio) are available for direct access when only a
specific component is needed.
est) in
persuasio| Situation | est argument |
|---|---|
| APR bounds + CI, have treatment variable | "apr" |
| LPR point estimate + CI | "lpr" |
| APR bounds + CI, only outcome and instrument | "yz" |
| Bounds from summary statistics | "calc" |
persuasio| Situation | Recommended method |
|---|---|
| No covariates, large sample | "normal" |
| Covariates present | "bootstrap" |
| Small sample regardless of covariates | "bootstrap" |
persuasio when covariates are
present| Identifying assumption | model |
|---|---|
| Homogeneous covariate effects across instrument groups | "no_interaction" |
| Heterogeneous covariate effects across groups | "interaction" |
| Unsure | "no_interaction" |
persuasio: Unified Wrapper for Persuasion Effect
Estimationpersuasio is the recommended entry point for the
package. Rather than calling aprlb, aprub,
lpr4ytz, or calc4persuasio directly,
persuasio provides a single interface that handles input
parsing and dispatches to the correct estimator based on the
est argument.
Example 1: Average persuasion rate (APR)
persuasio(
est = "apr",
y = "voteddem_all",
t = "readsome",
z = "post",
level = 0.80,
method = "normal",
data = GKB
)
#>
#> Average persuasion rate for binary outcomes, binary treatments and binary instruments
#>
#> Outcome: voteddem_all
#> Treatment: readsome
#> Instrument: post
#> Model: no_interaction
#> Method: normal
#> Observations: 701
#>
#> Estimates:
#> Lower Bound Upper Bound CI Lower CI Upper
#> 0.0707 0.6343 0.0288 0.6611
#>
#> Confidence level: 80%This dispatches to aprlb and aprub to
produce lower and upper bounds on the APR with asymptotic normal
confidence intervals at the 80% level.
Example 2: Local persuasion rate (LPR)
persuasio(
est = "lpr",
y = "voteddem_all",
t = "readsome",
z = "post",
level = 0.80,
method = "normal",
data = GKB
)
#>
#> Local persuasion rate for binary outcomes, binary treatments and binary instruments
#>
#> Outcome: voteddem_all
#> Treatment: readsome
#> Instrument: post
#> Model: no_interaction
#> Method: normal
#> Observations: 701
#>
#> Estimates:
#> LPR CI Lower CI Upper
#> 0.8067 0.1243 1
#>
#> Confidence level: 80%This dispatches to lpr4ytz to estimate the persuasion
effect among compliers and returns standard errors and confidence
intervals under the normal approximation.
Example 3: Outcome-instrument bounds with a covariate and bootstrap
persuasio(
est = "yz",
y = "voteddem_all",
z = "post",
x = "MZwave2",
data = GKB,
level = 0.80,
model = "interaction",
method = "bootstrap",
nboot = 100
)
#>
#> Average persuasion rate for binary outcomes and binary instruments
#>
#> Outcome: voteddem_all
#> Instrument: post
#> Model: interaction
#> Method: bootstrap
#> Observations: 701
#>
#> Estimates:
#> Lower Bound Upper Bound CI Lower CI Upper
#> 0.0725 1 0.0409 1
#>
#> Confidence level: 80%
#> Bootstrap replications: 100The "yz" estimator uses only the outcome and instrument,
making it suitable when the treatment variable is not observed.
MZwave2 is passed as a covariate with
model = "interaction", allowing heterogeneous covariate
effects across instrument groups. One hundred bootstrap replications are
used here for computational efficiency; at least 1,000 are recommended
for applied research.
This section details the lower-level functions in
persuasio.
| Situation | Base function |
|---|---|
| Lower bound on APR only | aprlb |
| Upper bound on APR only | aprub |
| Local persuasion rate (LPR) for compliers | lpr4ytz |
| Bounds from published group means, no microdata | calc4persuasio |
calc4persuasio: Bounds from Summary Statisticscalc4persuasio computes lower and upper bounds on
persuasion rates directly from group means by instrument status. This
function is useful when only published summary statistics are available,
or as a quick sanity check against aprlb and
aprub.
The function uses:
| Argument | Meaning |
|---|---|
y1 |
Mean of binary outcome y when instrument
z = 1 |
y0 |
Mean of binary outcome y when instrument
z = 0 |
e1 |
Mean of binary treatment t when instrument
z = 1 |
e0 |
Mean of binary treatment t when instrument
z = 0 |
Since calc4persuasio works on summary statistics, we
first compute group means manually:
voteddem_all_0 <- mean(GKB$voteddem_all[GKB$post == 0], na.rm = TRUE)
voteddem_all_1 <- mean(GKB$voteddem_all[GKB$post == 1], na.rm = TRUE)
readsome_0 <- mean(GKB$readsome[GKB$post == 0], na.rm = TRUE)
readsome_1 <- mean(GKB$readsome[GKB$post == 1], na.rm = TRUE)Then pass them to calc4persuasio:
calc4persuasio(
y1 = voteddem_all_1,
y0 = voteddem_all_0,
e1 = readsome_1,
e0 = readsome_0
)
#>
#> calc4persuasio: APR and LPR bounds given Pr(y=1|z) and optionally Pr(t=1|z) for z=0,1
#>
#> Case: with exposure rates
#>
#> APR bounds:
#> Lower Upper
#> 0.0707 0.7832
#>
#> LPR bounds:
#> Lower Upper
#> 0.7759 1
#>
#> Inputs:
#> y1 = 0.3461538, y0 = 0.2963855
#> e1 = 0.5629371, e0 = 0.4987952aprlb: Lower Bound on the Average Persuasion Rateaprlb estimates the lower bound on the average
persuasion rate (APR) following Jun and Lee (2023).
The function requires:
| Argument | Role | Must be binary? |
|---|---|---|
y |
Outcome | Yes |
z |
Instrument | Yes |
x |
Covariates, optional | No |
Example 1: No covariates
aprlb(y = "voteddem_all", z = "post", data = GKB)
#>
#> aprlb: Lower Bound of Average Persuasion Rate
#>
#> Outcome: voteddem_all
#> Instrument: post
#> Covariates: None
#> Model: no_interaction
#> Observations: 701
#>
#> Estimates:
#> Estimate Std. Error 95% CI Lower 95% CI Upper
#> 0.0707 0.0498 -0.0269 0.1684
#>
#> Note: It is recommended to use the 'persuasio' command.This estimates the lower bound without covariates, returning a coefficient, standard error, and 95% confidence interval.
Example 2: With a covariate, no-interaction model
aprlb(y = "voteddem_all", z = "post", x = "MZwave2", data = GKB)
#>
#> aprlb: Lower Bound of Average Persuasion Rate
#>
#> Outcome: voteddem_all
#> Instrument: post
#> Covariates: MZwave2
#> Model: no_interaction
#> Observations: 701
#>
#> Estimates:
#> Estimate Std. Error 95% CI Lower 95% CI Upper
#> 0.0719 NA NA NA
#>
#> Note: It is recommended to use the 'persuasio' command.With covariates and the default
model = "no_interaction", the function fits a single
regression with the instrument and covariates. Analytical standard
errors are not reported in this case; use a bootstrap wrapper for
inference.
Example 3: By subgroup
gkb_groups <- split(GKB, GKB$MZwave2)
lapply(gkb_groups, function(sub_data) {
aprlb(y = "voteddem_all", z = "post", data = sub_data)
})
#> $`0`
#>
#> aprlb: Lower Bound of Average Persuasion Rate
#>
#> Outcome: voteddem_all
#> Instrument: post
#> Covariates: None
#> Model: no_interaction
#> Observations: 443
#>
#> Estimates:
#> Estimate Std. Error 95% CI Lower 95% CI Upper
#> 0.0964 0.0632 -0.0274 0.2203
#>
#> Note: It is recommended to use the 'persuasio' command.
#>
#> $`1`
#>
#> aprlb: Lower Bound of Average Persuasion Rate
#>
#> Outcome: voteddem_all
#> Instrument: post
#> Covariates: None
#> Model: no_interaction
#> Observations: 258
#>
#> Estimates:
#> Estimate Std. Error 95% CI Lower 95% CI Upper
#> 0.0313 0.0816 -0.1287 0.1913
#>
#> Note: It is recommended to use the 'persuasio' command.This example computes aprlb separately for each value of
MZwave2 without covariates, producing estimates with
standard errors for each subgroup.
aprub: Upper Bound on the Average Persuasion Rateaprub estimates the upper bound on the average
persuasion rate (APR) following Jun and Lee (2023).
The function requires:
| Argument | Role | Must be binary? |
|---|---|---|
y |
Outcome | Yes |
t |
Treatment | Yes |
z |
Instrument | Yes |
x |
Covariates, optional | No |
Example 1: No covariates
aprub(y = "voteddem_all", t = "readsome", z = "post", data = GKB)
#>
#> aprub: Upper Bound of Average Persuasion Rate
#>
#> Outcome: voteddem_all
#> Instrument: post
#> Covariates: None
#> Model: no_interaction
#> Observations: 701
#>
#> Estimates:
#> Estimate Std. Error 95% CI Lower 95% CI Upper
#> 0.6343 0.0318 0.5719 0.6966
#> Note: It is recommended to use the 'persuasio' command.Without covariates, aprub estimates the upper bound
directly from the data and returns a coefficient, standard error, and
95% confidence interval.
Example 2: With a covariate, no-interaction model
aprub(y = "voteddem_all", t = "readsome", z = "post", x = "MZwave2", data = GKB)
#>
#> aprub: Upper Bound of Average Persuasion Rate
#>
#> Outcome: voteddem_all
#> Instrument: post
#> Covariates: MZwave2
#> Model: no_interaction
#> Observations: 701
#>
#> Estimates:
#> Estimate Std. Error 95% CI Lower 95% CI Upper
#> 0.6357 NA NA NA
#> Note: It is recommended to use the 'persuasio' command.With covariates and the default
model = "no_interaction", the function fits single
regressions with the instrument and covariates. Analytical standard
errors are not reported in this case; use a bootstrap wrapper for
inference.
Example 3: By subgroup
gkb_groups <- split(GKB, GKB$MZwave2)
lapply(gkb_groups, function(sub_data) {
aprub(y = "voteddem_all", t = "readsome", z = "post", data = sub_data)
})
#> $`0`
#>
#> aprub: Upper Bound of Average Persuasion Rate
#>
#> Outcome: voteddem_all
#> Instrument: post
#> Covariates: None
#> Model: no_interaction
#> Observations: 443
#>
#> Estimates:
#> Estimate Std. Error 95% CI Lower 95% CI Upper
#> 0.6773 0.0398 0.5994 0.7552
#> Note: It is recommended to use the 'persuasio' command.
#>
#> $`1`
#>
#> aprub: Upper Bound of Average Persuasion Rate
#>
#> Outcome: voteddem_all
#> Instrument: post
#> Covariates: None
#> Model: no_interaction
#> Observations: 258
#>
#> Estimates:
#> Estimate Std. Error 95% CI Lower 95% CI Upper
#> 0.5723 0.0517 0.4709 0.6736
#> Note: It is recommended to use the 'persuasio' command.This example computes the no-covariate aprub estimates
within each level of MZwave2, returning estimates with
standard errors for each subgroup.
lpr4ytz: Local Persuasion Ratelpr4ytz estimates the local persuasion rate (LPR), the
average persuasion effect among compliers. While aprlb and
aprub bound the APR across the full population, the LPR
focuses on the complier subpopulation.
The function requires:
| Argument | Role | Must be binary? |
|---|---|---|
y |
Outcome | Yes |
t |
Treatment | Yes |
z |
Instrument | Yes |
x |
Covariates, optional | No |
Example 1: No covariates
lpr4ytz(
y = "voteddem_all",
t = "readsome",
z = "post",
data = GKB
)
#>
#> lpr: Local Persuasion Rate
#>
#> Outcome: voteddem_all
#> Treatment: readsome
#> Instrument: post
#> Model: no_interaction
#> Observations: 701
#>
#> Estimates:
#> Estimate Std. Error 95% CI Lower 95% CI Upper
#> 0.8067 0.5325 0 1Without covariates, lpr4ytz returns the LPR estimate
along with a standard error and 95% confidence interval.
Example 2: With covariate, no-interaction model
lpr4ytz(
y = "voteddem_all",
t = "readsome",
z = "post",
x = "MZwave2",
data = GKB
)
#>
#> lpr: Local Persuasion Rate
#>
#> Outcome: voteddem_all
#> Treatment: readsome
#> Instrument: post
#> Model: no_interaction
#> Observations: 701
#>
#> Estimates:
#> Estimate Std. Error 95% CI Lower 95% CI Upper
#> 0.8312 0.543 0 1The default model = "no_interaction" fits single
regressions with the instrument and covariates. This is a parsimonious
specification and is appropriate when there is no strong prior reason to
expect heterogeneous covariate effects.
Example 3: With covariate, interaction model
lpr4ytz(
y = "voteddem_all",
t = "readsome",
z = "post",
x = "MZwave2",
model = "interaction",
data = GKB
)
#>
#> lpr: Local Persuasion Rate
#>
#> Outcome: voteddem_all
#> Treatment: readsome
#> Instrument: post
#> Model: interaction
#> Observations: 701
#>
#> Estimates:
#> Estimate Std. Error 95% CI Lower 95% CI Upper
#> 0.8453 NA NA NAThe model = "interaction" specification fits separate
models by instrument group, allowing the effect of MZwave2
to differ between the z = 1 and z = 0
subgroups. Analytical standard errors are not reported in this case.
Each inference wrapper calls the corresponding base function(s) for
point estimation, then adds confidence intervals via the chosen
inference method:
persuasio4ytz calls aprlb and
aprub jointly, combining the two bounds into a single
interval using either a Stoye (2009) normal correction or bootstrap
resampling.persuasio4yz uses only the reduced-form relationship
between outcome and instrument; the upper bound is fixed at 1.persuasio4ytz2lpr calls lpr4ytz for the
LPR point estimate and wraps it with a standard normal or bootstrap
confidence interval.In all three cases, persuasio is the recommended entry
point and dispatches to the appropriate wrapper internally. Call the
wrappers directly only when finer control over arguments is needed.
persuasio4ytz: Confidence Intervals for the Average
Persuasion RateWhen est = "apr" in persuasio,
persuasio4ytz is working under the hood. It combines lower
and upper bound estimates from aprlb and aprub
into a single confidence interval, using either an asymptotic normal
approximation or bootstrap resampling.
Example 1: No covariates, asymptotic normal approximation
persuasio4ytz(
y = "voteddem_all",
t = "readsome",
z = "post",
method = "normal",
level = 0.80,
data = GKB
)
#>
#> Average persuasion rate for binary outcomes, binary treatments and binary instruments
#>
#> Outcome: voteddem_all
#> Treatment: readsome
#> Instrument: post
#> Model: no_interaction
#> Method: normal
#> Observations: 701
#>
#> Estimates:
#> Lower Bound Upper Bound CI Lower CI Upper
#> 0.0707 0.6343 0.0288 0.6611
#>
#> Confidence level: 80%The asymptotic normal method is appropriate here because no
covariates are present and analytical standard errors are available from
both aprlb and aprub.
Example 2: No covariates, bootstrap inference
persuasio4ytz(
y = "voteddem_all",
t = "readsome",
z = "post",
method = "bootstrap",
level = 0.80,
nboot = 100,
data = GKB
)
#>
#> Average persuasion rate for binary outcomes, binary treatments and binary instruments
#>
#> Outcome: voteddem_all
#> Treatment: readsome
#> Instrument: post
#> Model: no_interaction
#> Method: bootstrap
#> Observations: 701
#>
#> Estimates:
#> Lower Bound Upper Bound CI Lower CI Upper
#> 0.0707 0.6343 0.0282 0.6624
#>
#> Confidence level: 80%
#> Bootstrap replications: 100Bootstrap inference provides an alternative to the normal approximation; results should be close to Example 1 in large samples. One hundred replications are used here for computational efficiency; at least 1,000 are recommended for applied research.
Example 3: With a covariate, interaction model, bootstrap inference
persuasio4ytz(
y = "voteddem_all",
t = "readsome",
z = "post",
x = "MZwave2",
model = "interaction",
method = "bootstrap",
level = 0.80,
nboot = 100,
data = GKB
)
#>
#> Average persuasion rate for binary outcomes, binary treatments and binary instruments
#>
#> Outcome: voteddem_all
#> Treatment: readsome
#> Instrument: post
#> Model: interaction
#> Method: bootstrap
#> Observations: 701
#>
#> Estimates:
#> Lower Bound Upper Bound CI Lower CI Upper
#> 0.0725 0.6378 0.0268 0.6675
#>
#> Confidence level: 80%
#> Bootstrap replications: 100When covariates are present, bootstrap inference is recommended.
Under model = "interaction", it is required because
analytical standard errors are not reported. The interaction
specification allows heterogeneous covariate effects across the
z = 1 and z = 0 subgroups.
persuasio4ytz2lpr: Confidence Intervals for the Local
Persuasion RateWhen est = "lpr" in persuasio,
persuasio4ytz2lpr is working under the hood. It is the
inference companion to lpr4ytz, wrapping the LPR point
estimate and adding confidence intervals via either a delta-method
normal approximation or bootstrap resampling.
With covariates, bootstrap inference is recommended. It is required when analytical standard errors are unavailable, especially under interaction models.
Example 1: No covariates, normal inference
persuasio4ytz2lpr(
y = "voteddem_all",
t = "readsome",
z = "post",
method = "normal",
level = 0.80,
data = GKB
)
#>
#> Local persuasion rate for binary outcomes, binary treatments and binary instruments
#>
#> Outcome: voteddem_all
#> Treatment: readsome
#> Instrument: post
#> Model: no_interaction
#> Method: normal
#> Observations: 701
#>
#> Estimates:
#> LPR CI Lower CI Upper
#> 0.8067 0.1243 1
#>
#> Confidence level: 80%The function uses the delta-method standard error from
lpr4ytz to construct an 80% confidence interval under the
normal approximation.
Example 2: No covariates, bootstrap inference
persuasio4ytz2lpr(
y = "voteddem_all",
t = "readsome",
z = "post",
method = "bootstrap",
level = 0.80,
nboot = 100,
data = GKB
)
#>
#> Local persuasion rate for binary outcomes, binary treatments and binary instruments
#>
#> Outcome: voteddem_all
#> Treatment: readsome
#> Instrument: post
#> Model: no_interaction
#> Method: bootstrap
#> Observations: 701
#>
#> Estimates:
#> LPR CI Lower CI Upper
#> 0.8067 0.2505 1
#>
#> Confidence level: 80%
#> Bootstrap replications: 100Bootstrap inference provides an alternative to the normal approximation. One hundred replications are used here for computational efficiency; at least 1,000 are recommended for applied research.
Example 3: With a covariate, interaction model, bootstrap inference
persuasio4ytz2lpr(
y = "voteddem_all",
t = "readsome",
z = "post",
x = "MZwave2",
model = "interaction",
method = "bootstrap",
level = 0.80,
nboot = 100,
data = GKB
)
#>
#> Local persuasion rate for binary outcomes, binary treatments and binary instruments
#>
#> Outcome: voteddem_all
#> Treatment: readsome
#> Instrument: post
#> Model: interaction
#> Method: bootstrap
#> Observations: 701
#>
#> Estimates:
#> LPR CI Lower CI Upper
#> 0.8453 0.1685 1
#>
#> Confidence level: 80%
#> Bootstrap replications: 100The model = "interaction" specification allows the
effect of MZwave2 to differ between the z = 1
and z = 0 subgroups. Bootstrap inference is used because
analytical standard errors are not reported in this case.
persuasio4yz: APR Bounds Without a Treatment
VariableWhen est = "yz" in persuasio,
persuasio4yz is working under the hood. It estimates bounds
on the APR using only the binary outcome y and binary
instrument z, and is appropriate when only the outcome and
instrument are observed.
Example 1: No covariates, normal inference
persuasio4yz(
y = "voteddem_all",
z = "post",
method = "normal",
level = 0.80,
data = GKB
)
#>
#> Average persuasion rate for binary outcomes and binary instruments
#>
#> Outcome: voteddem_all
#> Instrument: post
#> Model: no_interaction
#> Method: normal
#> Observations: 701
#>
#> Estimates:
#> Lower Bound Upper Bound CI Lower CI Upper
#> 0.0707 1 0.0288 1
#>
#> Confidence level: 80%Without covariates, the lower-bound analytical standard error is
available from aprlb; the upper bound is fixed at 1. The
normal approximation gives a one-sided confidence interval for the
identified set.
Example 2: No covariates, bootstrap inference
persuasio4yz(
y = "voteddem_all",
z = "post",
method = "bootstrap",
level = 0.80,
nboot = 100,
data = GKB
)
#>
#> Average persuasion rate for binary outcomes and binary instruments
#>
#> Outcome: voteddem_all
#> Instrument: post
#> Model: no_interaction
#> Method: bootstrap
#> Observations: 701
#>
#> Estimates:
#> Lower Bound Upper Bound CI Lower CI Upper
#> 0.0707 1 0.0316 1
#>
#> Confidence level: 80%
#> Bootstrap replications: 100Bootstrap inference resamples the lower-bound estimator. One hundred replications are used here for computational efficiency; at least 1,000 are recommended for applied research.
Example 3: With a covariate, interaction model, bootstrap inference
persuasio4yz(
y = "voteddem_all",
z = "post",
x = "MZwave2",
model = "interaction",
method = "bootstrap",
level = 0.80,
nboot = 100,
data = GKB
)
#>
#> Average persuasion rate for binary outcomes and binary instruments
#>
#> Outcome: voteddem_all
#> Instrument: post
#> Model: interaction
#> Method: bootstrap
#> Observations: 701
#>
#> Estimates:
#> Lower Bound Upper Bound CI Lower CI Upper
#> 0.0725 1 0.0417 1
#>
#> Confidence level: 80%
#> Bootstrap replications: 100With covariates, bootstrap inference is recommended. The
model = "interaction" specification allows heterogeneous
covariate effects of MZwave2 across instrument groups.
Jun, Sung Jae, and Sokbae Lee. 2023. “Identifying the Effect of Persuasion.” Journal of Political Economy 131 (8): 2032-2058. https://doi.org/10.1086/724114.