Getting Started with persuasio

Xinrui Chen

28 July, 2026

What is this for?

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).

When is 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.

Key estimands

persuasio TL;DR

persuasio 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.

Choosing an estimator (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"

Choosing an inference method in persuasio

Situation Recommended method
No covariates, large sample "normal"
Covariates present "bootstrap"
Small sample regardless of covariates "bootstrap"

Choosing a model in 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"

Package setup

library(persuasio)

The GKB data set is included in persuasio as lazy data, so it is available after loading the package. For a full description of the dataset, see GKB.R in the R folder or run ?GKB in the console.

persuasio: Unified Wrapper for Persuasion Effect Estimation

persuasio 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.

Examples using the GKB dataset

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: 100

The "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.

Base estimators

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 Statistics

calc4persuasio 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

Examples using the GKB dataset

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.4987952

aprlb: Lower Bound on the Average Persuasion Rate

aprlb 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

Examples using the GKB dataset

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 Rate

aprub 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

Examples using the GKB dataset

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 Rate

lpr4ytz 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

Examples using the GKB dataset

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            1

Without 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            1

The 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           NA

The 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.

Inference wrappers

Each inference wrapper calls the corresponding base function(s) for point estimation, then adds confidence intervals via the chosen inference method:

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 Rate

When 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.

Examples using the GKB dataset

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: 100

Bootstrap 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: 100

When 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 Rate

When 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.

Examples using the GKB dataset

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: 100

Bootstrap 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: 100

The 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 Variable

When 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: 100

Bootstrap 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: 100

With covariates, bootstrap inference is recommended. The model = "interaction" specification allows heterogeneous covariate effects of MZwave2 across instrument groups.

Reference

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.

mirror server hosted at Truenetwork, Russian Federation.