| Title: | Causal Inference with Spatio-Temporal Data |
|---|---|
| Description: | Methods for causal inference with spatio-temporal data. Point process tools estimate causal effects over specified spatial and temporal windows from treatment and outcome events. Unit-level longitudinal tools estimate propensity scores and evaluate or learn stochastic treatment policies for discrete spatial or administrative units. See Papadogeorgou, et al. (2022) <doi:10.1111/rssb.12548> and Mukaigawara, et al. (2024) <doi:10.31219/osf.io/5kc6f>. |
| Authors: | Mitsuru Mukaigawara [cre, aut] (ORCID: <https://orcid.org/0000-0001-6530-2083>), Lingxiao Zhou [aut], Georgia Papadogeorgou [aut] (ORCID: <https://orcid.org/0000-0002-1982-2245>), Jason Lyall [aut] (ORCID: <https://orcid.org/0000-0001-9117-7503>), Kosuke Imai [aut] (ORCID: <https://orcid.org/0000-0002-2748-1022>) |
| Maintainer: | Mitsuru Mukaigawara <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.4.2 |
| Built: | 2026-10-07 11:02:36 UTC |
| Source: | https://github.com/mmukaigawara/geocausal |
A dataset of airstrikes in Iraq (February to June 2007)
airstrikesairstrikes
A tibble with 3938 rows and 4 variables:
Date (YYYY-MM-DD)
Longitudes (decimal)
Latitudees (decimal)
Types of airstrikes (airstrikes or shows of force (SOF))
airstrikesairstrikes
A dataset of airstrikes in Iraq in 2006 (2006/1/1-2006/9/24)
airstrikes_2006airstrikes_2006
A tibble with 2101 rows and 4 variables:
Date (YYYY-MM-DD)
Longitudes (decimal)
Latitudees (decimal)
Types of airstrikes (airstrikes or shows of force (SOF))
airstrikes_2006airstrikes_2006
'conv_owin_into_sf' takes an owin object and converts it to sf-related objects. This function is mostly an internal function of other functions.
conv_owin_into_sf(window)conv_owin_into_sf(window)
window |
owin object |
'conv_owin_into_sf()' converts the window to a polygonal object, extracts its boundary coordinates (closing the ring if necessary), and returns the same boundary in several representations: an 'sf' 'POLYGON', a coordinate data frame, an 'sfc_POLYGON', an 'sf' object, and a 'SpatialPolygonsDataFrame'. It is mostly used internally by other functions that need different spatial object classes.
list of polygon, dataframe, sfc_POLYGON, sf, and SpatialPolygonsDataFrame objects
Other spatial utility functions:
get_dist_focus(),
get_dist_line(),
get_distexp(),
get_elev(),
get_window()
'dx_outpred()' performs out-of-sample prediction (separating data into training and test sets). It assumes that training and test sets have the same window.
dx_outpred( hfr, ratio, dep_var, indep_var, ndim = 128, resolution = NULL, window )dx_outpred( hfr, ratio, dep_var, indep_var, ndim = 128, resolution = NULL, window )
hfr |
hyperframe |
ratio |
numeric. ratio between training and test sets |
dep_var |
dependent variables |
indep_var |
independent variables |
ndim |
the number of grids. By default, '128' (128 x 128). |
resolution |
the resolution in km per pixel. If specified, overrides 'ndim'. For example, 'resolution = 5' creates ~5km x 5km grid cells. |
window |
owin object |
'dx_outpred()' splits the hyperframe chronologically into a training set (the first 'ratio' fraction of rows) and an implied test set, fits a Poisson point process model to the training data with 'spatstat.model::mppm()', and predicts the conditional intensity over the full hyperframe. It returns the predicted intensity images together with the integrated (estimated) event counts and the per-period sums of log intensities, which can be compared against observed counts to assess out-of-sample fit. Training and test sets are assumed to share the same window.
list of the following: * 'indep_var': independent variables * 'coef': coefficients * 'intens_grid_cells': im object of observed densities for each time period * 'estimated_counts': the number of events that is estimated by the poisson point process model for each time period * 'sum_log_intens': the sum of log intensities for each time period * 'training_row_max': the max row ID of the training set
Papadogeorgou, G., Imai, K., Lyall, J. and Li, F. (2022). Causal inference with spatio-temporal data: estimating the effects of airstrikes on insurgent violence in Iraq. Journal of the Royal Statistical Society Series B, 84(5), 1969–1999. doi:10.1111/rssb.12548
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
[get_obs_dens()]
Other diagnostic functions:
dx_supthin()
# Prepare data: airstrikes (treatment) in Iraq, 2006 (first 60 days) dat <- airstrikes_2006[airstrikes_2006$type == "Airstrike", ] dat$type <- "airstrike" dat$time <- as.numeric(dat$date - min(dat$date) + 1) dat <- dat[dat$time <= 60, ] hfr <- get_hfr(data = dat, col = "type", window = iraq_window, time_col = "time", time_range = c(1, 60), coordinates = c("longitude", "latitude"), combine = FALSE) hfr$dist_bag <- rep(list(get_dist_focus(window = iraq_window, lon = 44.366, lat = 33.315, ndim = 64)), nrow(hfr)) # Out-of-sample prediction with an 80/20 split pred <- dx_outpred(hfr, ratio = 0.8, dep_var = "airstrike", indep_var = "dist_bag", ndim = 64, window = iraq_window)# Prepare data: airstrikes (treatment) in Iraq, 2006 (first 60 days) dat <- airstrikes_2006[airstrikes_2006$type == "Airstrike", ] dat$type <- "airstrike" dat$time <- as.numeric(dat$date - min(dat$date) + 1) dat <- dat[dat$time <= 60, ] hfr <- get_hfr(data = dat, col = "type", window = iraq_window, time_col = "time", time_range = c(1, 60), coordinates = c("longitude", "latitude"), combine = FALSE) hfr$dist_bag <- rep(list(get_dist_focus(window = iraq_window, lon = 44.366, lat = 33.315, ndim = 64)), nrow(hfr)) # Out-of-sample prediction with an 80/20 split pred <- dx_outpred(hfr, ratio = 0.8, dep_var = "airstrike", indep_var = "dist_bag", ndim = 64, window = iraq_window)
'dx_supthin()' performs superthinning tests to examine model validity.
dx_supthin( hfr, dep_var, indep_var, window, rescale = 1, max_r = 50, n_sample = 1000, nsim = 1000, unit = "km" )dx_supthin( hfr, dep_var, indep_var, window, rescale = 1, max_r = 50, n_sample = 1000, nsim = 1000, unit = "km" )
hfr |
hyperframe |
dep_var |
The name of the dependent variable. Since we need to obtain the observed density of treatment events, 'dep_var' should be the name of the treatment variable. |
indep_var |
vector of names of independent variables (covariates) |
window |
owin object |
rescale |
conversion as needed (namely when the unit of distance of the owin object is in meters). By default = 1 (no conversion) |
max_r |
max distance in which the envelope tests are performed |
n_sample |
the number of points to sample. by default = 1000, if the number of points are smaller than this, no sampling is performed |
nsim |
the number of simulations to perform for the envelope tests |
unit |
distance units after conversion. By default "km" |
'dx_supthin()' assesses model validity through superthinning. It fits a Poisson point process model with 'spatstat.model::mppm()', then for each time period thins the observed points and superposes simulated points so that, under a correctly specified model, the combined pattern is approximately homogeneous Poisson at the constant rate 'cval'. Global envelope tests on the L- and K-functions ('spatstat.explore::envelope()') are computed on the pooled, optionally subsampled ('n_sample'), pattern using 'nsim' simulations out to 'max_r'. The returned 'supthin' data frame stacks the L- and K-function envelopes for plotting.
A list of resulting dataframe ('result_data'), windows ('window_list'), data for distance quantiles, and a window object for the entire window
Papadogeorgou, G., Imai, K., Lyall, J. and Li, F. (2022). Causal inference with spatio-temporal data: estimating the effects of airstrikes on insurgent violence in Iraq. Journal of the Royal Statistical Society Series B, 84(5), 1969–1999. doi:10.1111/rssb.12548
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
[get_obs_dens()]
Other diagnostic functions:
dx_outpred()
# Prepare data: airstrikes (treatment) in Iraq, 2006 (first 60 days) dat <- airstrikes_2006[airstrikes_2006$type == "Airstrike", ] dat$type <- "airstrike" dat$time <- as.numeric(dat$date - min(dat$date) + 1) dat <- dat[dat$time <= 60, ] hfr <- get_hfr(data = dat, col = "type", window = iraq_window, time_col = "time", time_range = c(1, 60), coordinates = c("longitude", "latitude"), combine = FALSE) hfr$dist_bag <- rep(list(get_dist_focus(window = iraq_window, lon = 44.366, lat = 33.315, ndim = 64)), nrow(hfr)) # Superthinning test (use a larger nsim in real applications) supthin <- dx_supthin(hfr, dep_var = "airstrike", indep_var = "dist_bag", window = iraq_window, nsim = 19)# Prepare data: airstrikes (treatment) in Iraq, 2006 (first 60 days) dat <- airstrikes_2006[airstrikes_2006$type == "Airstrike", ] dat$type <- "airstrike" dat$time <- as.numeric(dat$date - min(dat$date) + 1) dat <- dat[dat$time <= 60, ] hfr <- get_hfr(data = dat, col = "type", window = iraq_window, time_col = "time", time_range = c(1, 60), coordinates = c("longitude", "latitude"), combine = FALSE) hfr$dist_bag <- rep(list(get_dist_focus(window = iraq_window, lon = 44.366, lat = 33.315, ndim = 64)), nrow(hfr)) # Superthinning test (use a larger nsim in real applications) supthin <- dx_supthin(hfr, dep_var = "airstrike", indep_var = "dist_bag", window = iraq_window, nsim = 19)
'get_adaptive_baseline_dens()' takes a hyperframe for historical data and returns fitted densities for the current data. The output is used as counterfactural densities.
get_adaptive_baseline_dens( hfr_hist, hfr_current, dep_var, indep_var, ngrid = 100, window )get_adaptive_baseline_dens( hfr_hist, hfr_current, dep_var, indep_var, ngrid = 100, window )
hfr_hist |
hyperframe for historical data |
hfr_current |
hyperframe for current data |
dep_var |
The name of the dependent variable Since we need to obtain the counterfactural density of treatment events, 'dep_var' should be the name of the treatment variable. |
indep_var |
vector of names of independent variables (covariates) |
ngrid |
the number of grid cells that is used to generate observed densities. By default = 100. Notice that as you increase 'ngrid', the process gets computationally demanding. |
window |
owin object |
'get_adaptive_baseline_dens()' assumes the poisson point process model and calculates observed densities for each time period. It depends on 'spatstat.model::mppm()'. Users should note that the coefficients in the output are not directly interpretable, since they are the coefficients inside the exponential of the poisson model.
list of the following: * 'indep_var': independent variables * 'coef': coefficients * 'intens_grid_cells': im object of observed densities for each time period * 'estimated_counts': the number of events that is estimated by the poisson point process model for each time period * 'sum_log_intens': the sum of log intensities for each time period * 'actual_counts': the number of events (actual counts)
Other density estimation functions:
get_base_dens(),
get_cf_dens(),
get_cf_dens_adaptive(),
get_cf_sum_log_intens(),
get_obs_dens(),
get_power_dens(),
sim_cf_dens(),
sim_power_dens()
'get_base_dens()' takes a dataframe and returns the baseline densities using Scott's rule of thumb (out-of-sample data).
get_base_dens( window, ndim = 128, resolution = NULL, out_data = NULL, out_coordinates = c("longitude", "latitude"), input_crs = 4326, unit_scale = 1000 )get_base_dens( window, ndim = 128, resolution = NULL, out_data = NULL, out_coordinates = c("longitude", "latitude"), input_crs = 4326, unit_scale = 1000 )
window |
owin object |
ndim |
the number of dimensions of grid cells (ndim^2). By default, ndim = 128. |
resolution |
the resolution in km per pixel. If specified, overrides 'ndim'. For example, 'resolution = 5' creates ~5km x 5km grid cells. |
out_data |
dataframe |
out_coordinates |
vector of column names of longitudes and latitudes (in this order) |
input_crs |
the CRS of the input |
unit_scale |
parameter to convert meters to kilometers
(WGS84 decimal degrees). The function will transform these to match the |
'get_base_dens()' estimates a baseline (out-of-sample) density from point data supplied in 'out_data'. The points are projected to match the CRS attached to 'window', converted to a 'ppp' object, and smoothed by a kernel density estimate whose bandwidth is chosen by Scott's rule of thumb ('spatstat.explore::bw.scott()'). The result is normalized to integrate to one. The output grid is controlled either by 'ndim' or, if supplied, by 'resolution' (in km per pixel), which overrides 'ndim'. The window must carry a CRS attribute (e.g., created via 'get_window()' with a 'target_crs').
an im object of baseline density
Papadogeorgou, G., Imai, K., Lyall, J. and Li, F. (2022). Causal inference with spatio-temporal data: estimating the effects of airstrikes on insurgent violence in Iraq. Journal of the Royal Statistical Society Series B, 84(5), 1969–1999. doi:10.1111/rssb.12548
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
[get_cf_dens()]
Other density estimation functions:
get_adaptive_baseline_dens(),
get_cf_dens(),
get_cf_dens_adaptive(),
get_cf_sum_log_intens(),
get_obs_dens(),
get_power_dens(),
sim_cf_dens(),
sim_power_dens()
# Baseline density from out-of-sample (2007--2008) insurgency data base <- get_base_dens(window = iraq_window, ndim = 64, out_data = insurgencies, out_coordinates = c("longitude", "latitude"))# Baseline density from out-of-sample (2007--2008) insurgency data base <- get_base_dens(window = iraq_window, ndim = 64, out_data = insurgencies, out_coordinates = c("longitude", "latitude"))
A function that returns a Hajek estimator of CATE for a spatial or spatio-temporal effect modifier
get_cate( obs, cf1, cf2, treat, pixel_count_out, lag, trunc_level = 0.95, time_after = TRUE, entire_window = NULL, em = NULL, E_mat = NULL, nbase = 6, spline_type = "ns", intercept = TRUE, eval_values = NULL, eval_mat = NULL, test_beta = NULL, save_weights = TRUE, ... )get_cate( obs, cf1, cf2, treat, pixel_count_out, lag, trunc_level = 0.95, time_after = TRUE, entire_window = NULL, em = NULL, E_mat = NULL, nbase = 6, spline_type = "ns", intercept = TRUE, eval_values = NULL, eval_mat = NULL, test_beta = NULL, save_weights = TRUE, ... )
obs |
observed density |
cf1 |
counterfactual density 1 |
cf2 |
counterfactual density 2 |
treat |
column of a hyperframe that summarizes treatment data. In the form of 'hyperframe$column'. |
pixel_count_out |
column of a hyperframe that summarizes the number of outcome events in each pixel |
lag |
integer that specifies lags to calculate causal estimates. |
trunc_level |
the level of truncation for the weights (0-1). |
time_after |
whether to include one unit time difference between treatment and outcome. By default = TRUE |
entire_window |
owin object (the entire region of interest) |
em |
treat column of a hyperframe that summarizes the effect modifier data. In the form of 'hyperframe$column'. It can be NULL if E_mat is provided. |
E_mat |
optional covariance matrix (excluding the intercept) for the effect modifier. If provided, then the regression model will be based on this matrix. If 'intercept = TRUE', then a column of 1 will be add to 'E_mat'. |
nbase |
number of bases for splines |
spline_type |
type of splines. Either '"ns"' or '"bs"'. |
intercept |
whether to include intercept in the regression model. Default is TRUE. |
eval_values |
a vector of values of the effect modifier for which CATE will be evaluated. Default is a 'seq(a,b,length.out=20)' where 'a' and 'b' are minimum and maximum values of the effect modifier. |
eval_mat |
evaluated spline basis (excluding the intercept) matrix at 'eval_values'. If 'intercept = TRUE', then a column of 1 will be add to 'eval_mat'. |
test_beta |
a vector of integers contain the indices of the coefficients that are included in the hypothesis test. By default, the null hypothesis is that all coefficient (except the intercept is 0). See details below |
save_weights |
whether to save weights. Default is 'TRUE' |
... |
arguments passed onto the function |
'E_mat' should be a matrix or array of dimensions by where is the product of image dimensions and number of time period,
and is 'nbase'-'intercept'. If you want to construct your own covariate matrix 'E_mat', you should use 'get_em_vec()' to convert
the effect modifer(usually a column of a hyperframe) to a vector, and then construct the splines basis based on the vector. The covariate matrix'E_mat' should not
the column for intercept. The function 'get_cate()' will conduct a hypothesis testing on whether all the selected coefficients are 0. 'test_beta' is a vector of positive integers specifying the indices
of the chosen beta. The coefficients (except the intercept) are indexed by '1,2,...,nbase-intercept'. By default, it test whether all the coefficients(except the intercept) are 0, and this is testing the
the heterogeneity effect of the effect modifier.
list of the following: 'est_beta': estimated regression coefficient 'V_beta': estimated asymptotic covariance matrix of regression coefficient (normalized by total time periods) 'chisq_stat': observed chi-square statistics for the hypothesis test 'p.value': observed chi-square statistics for the hypothesis test 'specification': information about the specification of the spline basis and the values on which the CATE is estimated 'est_eval': estimated CATE evaluted at chosen values 'V_eval': estimated asymptotic covariance matrix of the estimated CATE values (normalized by total time periods) 'mean_effect': Mean of the pseudo pixel effect 'total_effect': Mean of the pseudo effect for the window 'entire_window'. It is equal to mean effect times the total number of pixels inside the chosen window
Zhou, L., Imai, K., Lyall, J. and Papadogeorgou, G. (2024). Estimating heterogeneous treatment effects for spatio-temporal causal inference: how economic assistance moderates the effects of airstrikes on insurgent violence. arXiv preprint. doi:10.48550/arXiv.2412.15128
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
[get_cate_sens()], [get_em_vec()], [pixel_count_ppp()]
Other causal effect estimation functions:
get_est(),
get_estimates(),
get_var_bound(),
get_weighted_surf()
# Prepare data: airstrikes (treatment) and insurgencies (outcome), Iraq 2006 dat <- rbind(airstrikes_2006[airstrikes_2006$type == "Airstrike", ], insurgencies_2006) dat$type <- ifelse(dat$type == "Airstrike", "airstrike", "insurgency") dat$time <- as.numeric(dat$date - min(dat$date) + 1) dat <- dat[dat$time <= 60, ] hfr <- get_hfr(data = dat, col = "type", window = iraq_window, time_col = "time", time_range = c(1, 60), coordinates = c("longitude", "latitude"), combine = FALSE) hfr$dist_bag <- rep(list(get_dist_focus(window = iraq_window, lon = 44.366, lat = 33.315, ndim = 64)), nrow(hfr)) # Observed density (propensity score) and counterfactual densities obs <- get_obs_dens(hfr, dep_var = "airstrike", indep_var = "dist_bag", ndim = 64, window = iraq_window) base <- get_base_dens(window = iraq_window, ndim = 64, out_data = insurgencies, out_coordinates = c("longitude", "latitude")) cf1 <- get_cf_dens(expected_number = 2, base_dens = base, window = iraq_window) cf2 <- get_cf_dens(expected_number = 4, base_dens = base, window = iraq_window) # Outcome counts by pixel, and CATE over the distance-from-Baghdad modifier hfr$pc_insurgency <- pixel_count_ppp(hfr$insurgency, ndim = 64) cate <- get_cate(obs = obs, cf1 = cf1, cf2 = cf2, treat = hfr$airstrike, pixel_count_out = hfr$pc_insurgency, lag = 1, entire_window = iraq_window, em = hfr$dist_bag, nbase = 4)# Prepare data: airstrikes (treatment) and insurgencies (outcome), Iraq 2006 dat <- rbind(airstrikes_2006[airstrikes_2006$type == "Airstrike", ], insurgencies_2006) dat$type <- ifelse(dat$type == "Airstrike", "airstrike", "insurgency") dat$time <- as.numeric(dat$date - min(dat$date) + 1) dat <- dat[dat$time <= 60, ] hfr <- get_hfr(data = dat, col = "type", window = iraq_window, time_col = "time", time_range = c(1, 60), coordinates = c("longitude", "latitude"), combine = FALSE) hfr$dist_bag <- rep(list(get_dist_focus(window = iraq_window, lon = 44.366, lat = 33.315, ndim = 64)), nrow(hfr)) # Observed density (propensity score) and counterfactual densities obs <- get_obs_dens(hfr, dep_var = "airstrike", indep_var = "dist_bag", ndim = 64, window = iraq_window) base <- get_base_dens(window = iraq_window, ndim = 64, out_data = insurgencies, out_coordinates = c("longitude", "latitude")) cf1 <- get_cf_dens(expected_number = 2, base_dens = base, window = iraq_window) cf2 <- get_cf_dens(expected_number = 4, base_dens = base, window = iraq_window) # Outcome counts by pixel, and CATE over the distance-from-Baghdad modifier hfr$pc_insurgency <- pixel_count_ppp(hfr$insurgency, ndim = 64) cate <- get_cate(obs = obs, cf1 = cf1, cf2 = cf2, treat = hfr$airstrike, pixel_count_out = hfr$pc_insurgency, lag = 1, entire_window = iraq_window, em = hfr$dist_bag, nbase = 4)
'get_cate_sens()' evaluates how robust conditional average treatment effect (CATE) estimates are to possible unmeasured confounding. The function projects each period-specific weighted surface onto the same effect-modifier basis used by 'get_cate()', and then checks whether each non-intercept basis coefficient can be shifted to zero under each sensitivity parameter 'gamma'.
get_cate_sens( obs, cf1, cf2, treat, pixel_count_out, lag, trunc_level = 0.95, time_after = TRUE, entire_window = NULL, em = NULL, E_mat = NULL, nbase = 6, spline_type = "ns", intercept = TRUE, eval_values = NULL, eval_mat = NULL, gamma_vals = seq(1.05, 1.2, by = 0.05), save_weights = TRUE, tol_slack = 1e-06, grid_init = 15, max_refine = 5, ... )get_cate_sens( obs, cf1, cf2, treat, pixel_count_out, lag, trunc_level = 0.95, time_after = TRUE, entire_window = NULL, em = NULL, E_mat = NULL, nbase = 6, spline_type = "ns", intercept = TRUE, eval_values = NULL, eval_mat = NULL, gamma_vals = seq(1.05, 1.2, by = 0.05), save_weights = TRUE, tol_slack = 1e-06, grid_init = 15, max_refine = 5, ... )
obs |
observed density |
cf1 |
counterfactual density 1 |
cf2 |
counterfactual density 2 |
treat |
column of a hyperframe that summarizes treatment data. In the form of 'hyperframe$column'. |
pixel_count_out |
column of a hyperframe that summarizes the number of outcome events in each pixel |
lag |
integer that specifies lags to calculate causal estimates. |
trunc_level |
the level of truncation for the weights (0-1). |
time_after |
whether to include one unit time difference between treatment and outcome. By default = TRUE |
entire_window |
owin object (the entire region of interest) |
em |
column of a hyperframe that summarizes the effect modifier data. In the form of 'hyperframe$column'. It can be NULL if 'E_mat' is provided. |
E_mat |
optional covariate matrix (excluding the intercept) for the effect modifier. |
nbase |
number of bases for splines |
spline_type |
type of splines. Either '"ns"' or '"bs"'. |
intercept |
whether to include intercept in the regression model. Default is TRUE. |
eval_values |
currently unused; reserved for future CATE-value sensitivity output. |
eval_mat |
currently unused; reserved for future CATE-value sensitivity output. |
gamma_vals |
numeric vector of sensitivity parameters (>= 1) at which to check zero-attainability. By default, 'seq(1.05, 1.2, by = 0.05)'. |
save_weights |
whether to save weights. Default is 'TRUE' |
tol_slack |
numeric tolerance used to determine whether zero is attainable. Default is '1e-6'. |
grid_init |
number of grid points used in each adaptive lambda search step. Default is 15. |
max_refine |
maximum number of adaptive lambda refinement steps. Default is 5. |
... |
arguments passed onto the spline basis function |
Unlike 'get_sens()', which returns lower and upper bounds for an average treatment effect, 'get_cate_sens()' checks zero-attainability for the projected coefficients. For each 'gamma', 'zero_attainable' indicates whether the corresponding non-intercept basis coefficient is no longer robust under the current allowance for unmeasured confounding. The 'robust_gamma' value summarizes the largest sensitivity level at which all included coefficients remain robust. The underlying linear programs are solved with 'Rglpk::Rglpk_solve_LP()'.
'gamma = 1' corresponds to no unmeasured confounding. Larger values allow more deviation from the observed treatment process.
list of the following: 'beta': a data frame with 'basis', 'gamma', and 'zero_attainable' for the non-intercept basis coefficients. 'robust_gamma': the smallest coefficient-specific robust gamma across all non-intercept basis coefficients. 'specification': information about the spline basis, evaluated values, and sensitivity parameters.
Zhou, L., Imai, K., Lyall, J. and Papadogeorgou, G. (2024). Estimating heterogeneous treatment effects for spatio-temporal causal inference: how economic assistance moderates the effects of airstrikes on insurgent violence. arXiv preprint. doi:10.48550/arXiv.2412.15128
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
Other sensitivity analysis functions:
get_sens()
'get_cf_dens' takes the target (expected) number, baseline density, and power density, and generates a hyperframe with counterfactual densities.
get_cf_dens(expected_number, base_dens, power_dens = NA, window)get_cf_dens(expected_number, base_dens, power_dens = NA, window)
expected_number |
the expected number of observations. |
base_dens |
baseline density (im object) |
power_dens |
power density (im object) |
window |
owin object |
There are two ways of generating counterfactual densities. First, users can keep the locations of observations as they are and change the expected number of observations. In this case, users do not have to set 'power_dens' and simply modify 'expected_number'. Alternatively, users can shift the locations as well. In this case, 'power_dens' must be specified. To obtain power densities, refer to [get_power_dens()].
an im object of a counterfactual density
Papadogeorgou, G., Imai, K., Lyall, J. and Li, F. (2022). Causal inference with spatio-temporal data: estimating the effects of airstrikes on insurgent violence in Iraq. Journal of the Royal Statistical Society Series B, 84(5), 1969–1999. doi:10.1111/rssb.12548
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
[get_obs_dens()], [get_est()]
Other density estimation functions:
get_adaptive_baseline_dens(),
get_base_dens(),
get_cf_dens_adaptive(),
get_cf_sum_log_intens(),
get_obs_dens(),
get_power_dens(),
sim_cf_dens(),
sim_power_dens()
# Baseline density from out-of-sample (2007--2008) insurgency data base <- get_base_dens(window = iraq_window, ndim = 64, out_data = insurgencies, out_coordinates = c("longitude", "latitude")) # Counterfactual scenario: two airstrikes per day on average, # distributed proportionally to the baseline density cf <- get_cf_dens(expected_number = 2, base_dens = base, window = iraq_window)# Baseline density from out-of-sample (2007--2008) insurgency data base <- get_base_dens(window = iraq_window, ndim = 64, out_data = insurgencies, out_coordinates = c("longitude", "latitude")) # Counterfactual scenario: two airstrikes per day on average, # distributed proportionally to the baseline density cf <- get_cf_dens(expected_number = 2, base_dens = base, window = iraq_window)
'get_cf_dens_adaptive' takes the scale_factor, baseline density to construct counterfactural intensities .
get_cf_dens_adaptive(baseline_den, scale_factor)get_cf_dens_adaptive(baseline_den, scale_factor)
baseline_den |
baseline density (obs object obtained from 'get_adaptive_baseline_dens') |
scale_factor |
a positive number that scales the baseline intensity |
a list of the following: * 'intens_grid_cells': im object of counterfactural intensities for each time period * 'estimated_counts': the number of events that is estimated by the poisson point process model for each time period * 'sum_log_intens': the sum of log intensities for each time period
Other density estimation functions:
get_adaptive_baseline_dens(),
get_base_dens(),
get_cf_dens(),
get_cf_sum_log_intens(),
get_obs_dens(),
get_power_dens(),
sim_cf_dens(),
sim_power_dens()
A function that takes a hyperframe and returns the log counterfactual densities ie, the numerator of the equation
get_cf_sum_log_intens(cf_dens, treatment_data)get_cf_sum_log_intens(cf_dens, treatment_data)
cf_dens |
A counterfactual density (an im object or a list of im objects) |
treatment_data |
In the form of hyperframe$column |
'get_cf_sum_log_intens()' evaluates a counterfactual density at the observed treatment locations for each time period using bilinear interpolation ('spatstat.geom::interp.im()'), and returns the sum of the log intensities per period. 'cf_dens' may be a single 'im' object reused across all periods or a list of 'im' objects with one per period. Points falling on the boundary, where the intensity cannot be interpolated, are dropped; a period with no usable points contributes a sum of zero.
A numeric vector of sums of log densities for each time period
Papadogeorgou, G., Imai, K., Lyall, J. and Li, F. (2022). Causal inference with spatio-temporal data: estimating the effects of airstrikes on insurgent violence in Iraq. Journal of the Royal Statistical Society Series B, 84(5), 1969–1999. doi:10.1111/rssb.12548
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
Other density estimation functions:
get_adaptive_baseline_dens(),
get_base_dens(),
get_cf_dens(),
get_cf_dens_adaptive(),
get_obs_dens(),
get_power_dens(),
sim_cf_dens(),
sim_power_dens()
'get_dist_focus()' generates a distance map from focus locations.
get_dist_focus( window, lon, lat, resolution = NULL, ndim = NULL, mile = FALSE, preprocess = FALSE, input_crs = 4326, unit_scale = 1000 )get_dist_focus( window, lon, lat, resolution = NULL, ndim = NULL, mile = FALSE, preprocess = FALSE, input_crs = 4326, unit_scale = 1000 )
window |
owin object |
lon |
vector of longitudes |
lat |
vector of latitudes |
resolution |
resolution of raster (distance map) (in km; by default, 1). Ignored if npixel is set. |
ndim |
number of pixels for both dimensions (e.g., 256 for 256x256). If set, resolution is ignored. |
mile |
logical. 'mile' specifies whether to return the output in miles instead of kilometers (by default, FALSE). |
preprocess |
logical. 'preprocess' specifies whether to first pick the potentially closest point. It is recommended to set 'preprocess = TRUE' if users need to obtain distances from many points. |
input_crs |
the CRS of the focus points (defaults to 4326). These points are internally projected to match the window CRS to ensure isotropic distance calculations. |
unit_scale |
set to the same value as the parameter in 'get_window()' function. This parameter converts the coordinate values so that they alingn with the unit (km) of the owin object |
This function performs its computation using the 'future' framework (via 'furrr'); to run it in parallel, set 'future::plan(future::multisession)' before calling this function. The results are identical regardless of the plan.
an im object
Other spatial utility functions:
conv_owin_into_sf(),
get_dist_line(),
get_distexp(),
get_elev(),
get_window()
'get_dist_line()' generates a distance map from lines and polygons.
get_dist_line( window, path_to_shapefile = NULL, line_data = NULL, mile = FALSE, resolution = NULL, ndim = NULL, preprocess = TRUE, unit_scale = 1000 )get_dist_line( window, path_to_shapefile = NULL, line_data = NULL, mile = FALSE, resolution = NULL, ndim = NULL, preprocess = TRUE, unit_scale = 1000 )
window |
owin object |
path_to_shapefile |
path to shapefile |
line_data |
sfc_MULTILINESTRING file (If available. If not, 'get_dist_line()' creates it from a shapefile.) |
mile |
logical. 'mile' specifies whether to return the output in miles instead of kilometers (by default, FALSE). |
resolution |
resolution of raster objects (distance map) (in km; by default, 1). Ignored if ndim is set. |
ndim |
number of pixels for both dimensions (e.g., 256 for 256x256). If set, resolution is ignored. |
preprocess |
logical. 'preprocess' specifies whether to first pick the potentially closest point. It is recommended to set 'preprocess = TRUE' if users need to obtain distances from many points. |
unit_scale |
set to the same value as the parameter in 'get_window()' function. This parameter converts the coordinate values so that they alingn with the unit (km) of the owin object |
The function ensures spatial integrity by automatically projecting the
line_data or shapefile to match the Coordinate Reference System (CRS)
of the window.
This function performs its computation using the 'future' framework (via 'furrr'); to run it in parallel, set 'future::plan(future::multisession)' before calling this function. The results are identical regardless of the plan.
an im object
Other spatial utility functions:
conv_owin_into_sf(),
get_dist_focus(),
get_distexp(),
get_elev(),
get_window()
'get_distexp()' takes counterfactual densities and and returns the expected number of treatment events based on distances from a user-specified focus.
get_distexp( cf_sim_results, entire_window, dist_map, dist_map_unit = "km", use_raw = FALSE )get_distexp( cf_sim_results, entire_window, dist_map, dist_map_unit = "km", use_raw = FALSE )
cf_sim_results |
output of 'sim_cf_dens()' |
entire_window |
owin object of the entire region |
dist_map |
im object whose cell values are the distance from a focus (e.g., city) |
dist_map_unit |
either '"km"' or '"mile"' |
use_raw |
logical. 'use_raw' specifies whether to use the raw value of expectations or percentiles. By default, 'FALSE'. |
'get_distexp()' builds a sequence of nested sub-windows defined by percentiles of the distance map 'dist_map', then integrates each simulated counterfactual density over those sub-windows to obtain the expected number of treatment events within each distance band. By default the expectations are standardized by the total integral of the first counterfactual density; set 'use_raw = TRUE' to return raw expected counts instead. The output is a 'distlist' object suitable for plotting.
A list of resulting dataframe ('result_data'), windows ('window_list'), data for distance quantiles, and a window object for the entire window
Other spatial utility functions:
conv_owin_into_sf(),
get_dist_focus(),
get_dist_line(),
get_elev(),
get_window()
'get_elev()' takes a directory that hosts shapefile and returns an owin object of altitudes.
get_elev(load_path, ...)get_elev(load_path, ...)
load_path |
path to the shp file (note: a folder) |
... |
other parameters passed to 'elevatr::get_elev_raster()'. The resolution argument z must be specified. |
'get_elev()' reads a shapefile and downloads elevation data clipped to that region via 'elevatr::get_elev_raster()' (the resolution argument 'z' must be passed through '...'). The raster is then converted into a 'spatstat.geom::im' object, flipping the matrix vertically so that the raster (top-left origin) aligns with the 'spatstat' (bottom-left origin) convention.
an im object (unit: meters)
Other spatial utility functions:
conv_owin_into_sf(),
get_dist_focus(),
get_dist_line(),
get_distexp(),
get_window()
'get_em_vec()' get the vector form of a column of a hyperframe that summarizes the effect modifier data in heterogeneity analysis
get_em_vec( em, outcome_pixel_count = NULL, time_after = TRUE, entire_window = NULL, lag )get_em_vec( em, outcome_pixel_count = NULL, time_after = TRUE, entire_window = NULL, lag )
em |
column of a hyperframe that summarizes effect modifier data. In the form of 'hyperframe$column'. |
outcome_pixel_count |
A list of integer-valued pixel images giving outcome event counts per spatial pixel, typically obtained from 'pixel_count_ppp()'. |
time_after |
whether to include one unit time difference between treatment and outcome. By default = TRUE |
entire_window |
owin object (the entire region of interest). If given, then the values outside the region will be set to 'NA'. |
lag |
integer that specifies lags to calculate causal estimates |
The function 'get_em_vec()' get the vector form of the effect modifier in the heterogeneity analysis. It is useful if you want to construct the variance matrix 'E_mat' that is passed to the function 'get_cate()'
a numeric vector giving the effect modifier values, flattened across pixels and time periods, with values outside 'entire_window' (if supplied) set to 'NA'.
Zhou, L., Imai, K., Lyall, J. and Papadogeorgou, G. (2024). Estimating heterogeneous treatment effects for spatio-temporal causal inference: how economic assistance moderates the effects of airstrikes on insurgent violence. arXiv preprint. doi:10.48550/arXiv.2412.15128
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
Other data preparation functions:
get_hfr(),
get_hist(),
imls_to_arr(),
pixel_count_ppp(),
smooth_ppp()
'get_est()' generates causal estimates comparing two counterfactual scenarios.
get_est( obs, cf1, cf2, treat, sm_out, mediation = FALSE, obs_med_log_sum_dens = NA, cf1_med_log_sum_dens = NA, cf2_med_log_sum_dens = NA, lag, time_after = TRUE, entire_window, use_dist, windows, dist_map, dist, trunc_level = NA, save_weights = TRUE )get_est( obs, cf1, cf2, treat, sm_out, mediation = FALSE, obs_med_log_sum_dens = NA, cf1_med_log_sum_dens = NA, cf2_med_log_sum_dens = NA, lag, time_after = TRUE, entire_window, use_dist, windows, dist_map, dist, trunc_level = NA, save_weights = TRUE )
obs |
observed density |
cf1 |
counterfactual density 1 |
cf2 |
counterfactual density 2 |
treat |
column of a hyperframe that summarizes treatment data. In the form of 'hyperframe$column'. |
sm_out |
column of a hyperframe that summarizes the smoothed outcome data |
mediation |
whether to perform causal mediation analysis (don't use; still in development). By default, FALSE. |
obs_med_log_sum_dens |
sum of log densities of mediators for the observed (don't use; still in development) |
cf1_med_log_sum_dens |
sum of log densities of mediators for counterfactual 1 (don't use; still in development) |
cf2_med_log_sum_dens |
sum of log densities of mediators for counterfactual 2 (don't use; still in development) |
lag |
integer that specifies lags to calculate causal estimates |
time_after |
whether to include one unit time difference between treatment and outcome. By default = TRUE |
entire_window |
owin object (the entire region of interest) |
use_dist |
whether to use distance-based maps. By default, TRUE |
windows |
a list of owin objects (if 'use_dist = FALSE') |
dist_map |
distance map (an im object, if 'use_dist = TRUE') |
dist |
distances (a numeric vector within the max distance of 'dist_map') |
trunc_level |
the level of truncation for the weights (0-1) |
save_weights |
whether to save weights |
The level of truncation indicates the quantile of weights at which weights are truncated. That is, if 'trunc_level = 0.95', then all weights are truncated at the 95 percentile of the weights.
list of the following: 'cf1_ave_surf': average weighted surface for scenario 1 'cf2_ave_surf': average weighted surface for scenario 2 'est_cf': estimated effects of each scenario 'est_causal': estimated causal contrasts 'var_cf': variance upper bounds for each scenario 'var_causal': variance upper bounds for causal contrasts 'windows': list of owin objects
Papadogeorgou, G., Imai, K., Lyall, J. and Li, F. (2022). Causal inference with spatio-temporal data: estimating the effects of airstrikes on insurgent violence in Iraq. Journal of the Royal Statistical Society Series B, 84(5), 1969–1999. doi:10.1111/rssb.12548
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
[get_obs_dens()], [get_cf_dens()], [get_sens()]
Other causal effect estimation functions:
get_cate(),
get_estimates(),
get_var_bound(),
get_weighted_surf()
# Prepare data: airstrikes (treatment) and insurgencies (outcome), Iraq 2006 dat <- rbind(airstrikes_2006[airstrikes_2006$type == "Airstrike", ], insurgencies_2006) dat$type <- ifelse(dat$type == "Airstrike", "airstrike", "insurgency") dat$time <- as.numeric(dat$date - min(dat$date) + 1) dat <- dat[dat$time <= 60, ] hfr <- get_hfr(data = dat, col = "type", window = iraq_window, time_col = "time", time_range = c(1, 60), coordinates = c("longitude", "latitude"), combine = FALSE) dist_baghdad <- get_dist_focus(window = iraq_window, lon = 44.366, lat = 33.315, ndim = 64) hfr$dist_bag <- rep(list(dist_baghdad), nrow(hfr)) # Observed density (propensity score) and counterfactual densities obs <- get_obs_dens(hfr, dep_var = "airstrike", indep_var = "dist_bag", ndim = 64, window = iraq_window) base <- get_base_dens(window = iraq_window, ndim = 64, out_data = insurgencies, out_coordinates = c("longitude", "latitude")) cf1 <- get_cf_dens(expected_number = 2, base_dens = base, window = iraq_window) cf2 <- get_cf_dens(expected_number = 4, base_dens = base, window = iraq_window) # Smoothed outcomes hfr$sm_insurgency <- smooth_ppp(hfr$insurgency, method = "abramson", ndim = 64) # Causal estimates comparing the two scenarios est <- get_est(obs = obs, cf1 = cf1, cf2 = cf2, treat = hfr$airstrike, sm_out = hfr$sm_insurgency, lag = 1, entire_window = iraq_window, use_dist = TRUE, dist_map = dist_baghdad, dist = c(100, 200, 300), trunc_level = 0.95)# Prepare data: airstrikes (treatment) and insurgencies (outcome), Iraq 2006 dat <- rbind(airstrikes_2006[airstrikes_2006$type == "Airstrike", ], insurgencies_2006) dat$type <- ifelse(dat$type == "Airstrike", "airstrike", "insurgency") dat$time <- as.numeric(dat$date - min(dat$date) + 1) dat <- dat[dat$time <= 60, ] hfr <- get_hfr(data = dat, col = "type", window = iraq_window, time_col = "time", time_range = c(1, 60), coordinates = c("longitude", "latitude"), combine = FALSE) dist_baghdad <- get_dist_focus(window = iraq_window, lon = 44.366, lat = 33.315, ndim = 64) hfr$dist_bag <- rep(list(dist_baghdad), nrow(hfr)) # Observed density (propensity score) and counterfactual densities obs <- get_obs_dens(hfr, dep_var = "airstrike", indep_var = "dist_bag", ndim = 64, window = iraq_window) base <- get_base_dens(window = iraq_window, ndim = 64, out_data = insurgencies, out_coordinates = c("longitude", "latitude")) cf1 <- get_cf_dens(expected_number = 2, base_dens = base, window = iraq_window) cf2 <- get_cf_dens(expected_number = 4, base_dens = base, window = iraq_window) # Smoothed outcomes hfr$sm_insurgency <- smooth_ppp(hfr$insurgency, method = "abramson", ndim = 64) # Causal estimates comparing the two scenarios est <- get_est(obs = obs, cf1 = cf1, cf2 = cf2, treat = hfr$airstrike, sm_out = hfr$sm_insurgency, lag = 1, entire_window = iraq_window, use_dist = TRUE, dist_map = dist_baghdad, dist = c(100, 200, 300), trunc_level = 0.95)
A function that returns a Hajek estimator of causal contrasts
get_estimates( weighted_surf_1, weighted_surf_2, use_dist = TRUE, windows, dist_map, dist, entire_window )get_estimates( weighted_surf_1, weighted_surf_2, use_dist = TRUE, windows, dist_map, dist, entire_window )
weighted_surf_1 |
a weighted surface for scenario 1 |
weighted_surf_2 |
another weighted surface for scenario 2 |
use_dist |
whether to use distance-based maps. By default, TRUE |
windows |
a list of owin objects (if 'use_dist = FALSE') |
dist_map |
distance map (an im object, if 'use_dist = TRUE') |
dist |
distances (a numeric vector within the max distance of 'dist_map') |
entire_window |
an owin object of the entire map |
'get_estimates()' is an internal function to 'get_est()' function, performing the estimation analysis after 'get_weighted_surf()' function
list of Hajek estimators for each scenario ('est_haj'), causal contrasts (Hajek estimator) as a matrix ('est_tau_haj_matrix'), and causal contrast (scenario 2 - scenario 1) as a numeric vector ('est_tau_haj_cf2_vs_cf1'), along with weights, windows, and smoothed outcomes
Papadogeorgou, G., Imai, K., Lyall, J. and Li, F. (2022). Causal inference with spatio-temporal data: estimating the effects of airstrikes on insurgent violence in Iraq. Journal of the Royal Statistical Society Series B, 84(5), 1969–1999. doi:10.1111/rssb.12548
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
Other causal effect estimation functions:
get_cate(),
get_est(),
get_var_bound(),
get_weighted_surf()
'get_hfr()' takes a dataframe with time and location variables and generates a hyperframe with point patterns.
get_hfr( data, col, window, time_col, time_range, coordinates = c("longitude", "latitude"), combine = TRUE, input_crs = 4326, unit_scale = 1000, check_duplicates = FALSE )get_hfr( data, col, window, time_col, time_range, coordinates = c("longitude", "latitude"), combine = TRUE, input_crs = 4326, unit_scale = 1000, check_duplicates = FALSE )
data |
dataframe. The dataframe must have time and location variables. |
col |
the name of the column for types of events of interest |
window |
owin object (for more information, refer to 'spatstat.geom::owin()').
Must be a projected window (e.g., created via |
time_col |
the name of the column for time variable. Note that the time variable must be integers. |
time_range |
numeric vector. 'time_range' specifies the range of the time variable (i.e., min and max of the time variable). The current version assumes that the unit of this time variable is dates. |
coordinates |
character vector. 'coordinates' specifies the names of columns for locations. By default, 'c("longitude", "latitude")' in this order. Note that the coordinates must be in decimal degree formats. |
combine |
logical. 'combine' tells whether to generate output for all subtypes of events combined. By default, 'TRUE', which means that a column of ppp objects with all subtypes combined is generated in the output. |
input_crs |
the CRS of the input |
unit_scale |
parameter to convert meters to kilometers |
check_duplicates |
logical. 'check_duplicates' specifies whether to run ‘spatstat'’s duplicate-point check when constructing the point pattern of each time period. By default, 'FALSE', so the check (and the warning "data contain duplicated points") is skipped, because coincident events are legitimate in event data. Set to 'TRUE' to re-enable the check as a diagnostic for possible data-recording issues; the constructed point patterns are identical either way. |
Event data often contain multiple events at identical coordinates (e.g., several events recorded at the same location within one time period). Such duplicated points are legitimate observations and are retained as they are; each point contributes separately to subsequent intensity estimation. For this reason, ‘get_hfr()' skips 'spatstat'’s duplicate-point check by default ('check_duplicates = FALSE'), so the warning "data contain duplicated points" is not issued. Set 'check_duplicates = TRUE' to re-enable the check as a diagnostic for potential data-recording issues. Downstream functions that pool points across time periods (e.g., 'get_hist()', 'smooth_ppp()', 'get_base_dens()', 'dx_supthin()') always skip the check, since duplicates are unavoidable there.
A hyperframe is generated with rows representing time and columns representing the following: * The first column: time variable * The middle columns: ppp objects (see 'spatstat.geom::ppp()') generated for each subtype of events of interest * The last column (if 'combine = TRUE'): ppp objects with all subtypes combined. This column is named as 'all_combined'.
[get_window()], [smooth_ppp()]
Other data preparation functions:
get_em_vec(),
get_hist(),
imls_to_arr(),
pixel_count_ppp(),
smooth_ppp()
# Data dat <- data.frame(time = c(1, 1, 2, 2), longitude = c(43.9, 44.5, 44.1, 44.0), latitude = c(33.6, 32.7, 33.6, 33.5), type = rep(c("treat", "out"), 2)) # Hyperframe get_hfr(data = dat, col = "type", window = iraq_window, time_col = "time", time_range = c(1, 2), coordinates = c("longitude", "latitude"), combine = FALSE)# Data dat <- data.frame(time = c(1, 1, 2, 2), longitude = c(43.9, 44.5, 44.1, 44.0), latitude = c(33.6, 32.7, 33.6, 33.5), type = rep(c("treat", "out"), 2)) # Hyperframe get_hfr(data = dat, col = "type", window = iraq_window, time_col = "time", time_range = c(1, 2), coordinates = c("longitude", "latitude"), combine = FALSE)
'get_hist()' takes a hyperframe and time and columns of interest, and generates histories of events of interest.
get_hist(tt, Xt, Yt = NA, lag, window, x_only = TRUE)get_hist(tt, Xt, Yt = NA, lag, window, x_only = TRUE)
tt |
values of the time variable of interest for which 'get_hist()' generates histories |
Xt |
the name of a treatment column |
Yt |
the name of an outcome column |
lag |
numeric. 'lag' specifies the number of time periods over which 'get_hist()' aggregates treatment and outcome columns. |
window |
owin object. |
x_only |
logical. 'x_only' specifies whether to generate only treatment history (no outcome history). By default, 'FALSE'. |
list of treatment and outcome histories
Other data preparation functions:
get_em_vec(),
get_hfr(),
imls_to_arr(),
pixel_count_ppp(),
smooth_ppp()
dat_out <- insurgencies[1:100, ] dat_out$time <- as.numeric(dat_out$date - min(dat_out$date) + 1) # Hyperframe dat_hfr <- get_hfr(data = dat_out, col = "type", window = iraq_window, time_col = "time", time_range = c(1, max(dat_out$time)), coordinates = c("longitude", "latitude"), combine = TRUE) # Histories lapply(1:nrow(dat_hfr), get_hist, Xt = dat_hfr$all_outcome, lag = 1, window = iraq_window)dat_out <- insurgencies[1:100, ] dat_out$time <- as.numeric(dat_out$date - min(dat_out$date) + 1) # Hyperframe dat_hfr <- get_hfr(data = dat_out, col = "type", window = iraq_window, time_col = "time", time_range = c(1, max(dat_out$time)), coordinates = c("longitude", "latitude"), combine = TRUE) # Histories lapply(1:nrow(dat_hfr), get_hist, Xt = dat_hfr$all_outcome, lag = 1, window = iraq_window)
Solves the pair of linear programs that yield the upper and lower bounds of the Hajek-weighted estimand under a given sensitivity parameter 'gamma'. Used internally by 'get_sens()'.
get_linear_prog(wto, this_gamma)get_linear_prog(wto, this_gamma)
wto |
list whose first element is the numerator (daily Hajek-weighted outcomes) and whose second element is the denominator (daily Hajek weights for the window of interest), as returned by 'sens_weighted_surf()'. |
this_gamma |
sensitivity parameter (>= 1). 'gamma = 1' corresponds to no unmeasured confounding. |
'get_linear_prog()' is an internal function to 'get_sens()'. It relies on 'Rglpk::Rglpk_solve_LP()' to solve the transformed linear program.
a tibble with columns 'high' and 'low' giving the upper and lower bounds of the estimand at 'this_gamma'.
'get_obs_dens()' takes a hyperframe and returns observed densities. The output is used as propensity scores.
get_obs_dens(hfr, dep_var, indep_var, ndim = 128, resolution = NULL, window)get_obs_dens(hfr, dep_var, indep_var, ndim = 128, resolution = NULL, window)
hfr |
hyperframe |
dep_var |
The name of the dependent variable. Since we need to obtain the observed density of treatment events, 'dep_var' should be the name of the treatment variable. |
indep_var |
vector of names of independent variables (covariates) |
ndim |
the number of grid cells that is used to generate observed densities. By default = 128 (128 x 128). Notice that as you increase 'ndim', the process gets computationally demanding. |
resolution |
the resolution in km per pixel. If specified, overrides 'ndim'. For example, 'resolution = 5' creates ~5km x 5km grid cells. |
window |
owin object |
'get_obs_dens()' assumes the poisson point process model and calculates observed densities for each time period. It depends on 'spatstat.model::mppm()'. Users should note that the coefficients in the output are not directly interpretable, since they are the coefficients inside the exponential of the poisson model.
list of the following: * 'indep_var': independent variables * 'coef': coefficients * 'deviance': deviance * 'null_deviance': null deviance * 'dispersion': dispersion parameter * 'res_df': average residuals as a dataframe * 'intens_grid_cells': im object of observed densities for each time period * 'estimated_counts': the number of events that is estimated by the poisson point process model for each time period * 'sum_log_intens': the sum of log intensities for each time period * 'actual_counts': the number of events (actual counts) * 'window': window object used as an input
Papadogeorgou, G., Imai, K., Lyall, J. and Li, F. (2022). Causal inference with spatio-temporal data: estimating the effects of airstrikes on insurgent violence in Iraq. Journal of the Royal Statistical Society Series B, 84(5), 1969–1999. doi:10.1111/rssb.12548
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
[get_cf_dens()], [get_est()]
Other density estimation functions:
get_adaptive_baseline_dens(),
get_base_dens(),
get_cf_dens(),
get_cf_dens_adaptive(),
get_cf_sum_log_intens(),
get_power_dens(),
sim_cf_dens(),
sim_power_dens()
# Prepare data: airstrikes (treatment) and insurgencies (outcome), Iraq 2006 dat <- rbind(airstrikes_2006[airstrikes_2006$type == "Airstrike", ], insurgencies_2006) dat$type <- ifelse(dat$type == "Airstrike", "airstrike", "insurgency") dat$time <- as.numeric(dat$date - min(dat$date) + 1) dat <- dat[dat$time <= 60, ] hfr <- get_hfr(data = dat, col = "type", window = iraq_window, time_col = "time", time_range = c(1, 60), coordinates = c("longitude", "latitude"), combine = FALSE) # Covariate surface: distance from Baghdad hfr$dist_bag <- rep(list(get_dist_focus(window = iraq_window, lon = 44.366, lat = 33.315, ndim = 64)), nrow(hfr)) # Observed density of the treatment (propensity score) obs <- get_obs_dens(hfr, dep_var = "airstrike", indep_var = "dist_bag", ndim = 64, window = iraq_window)# Prepare data: airstrikes (treatment) and insurgencies (outcome), Iraq 2006 dat <- rbind(airstrikes_2006[airstrikes_2006$type == "Airstrike", ], insurgencies_2006) dat$type <- ifelse(dat$type == "Airstrike", "airstrike", "insurgency") dat$time <- as.numeric(dat$date - min(dat$date) + 1) dat <- dat[dat$time <= 60, ] hfr <- get_hfr(data = dat, col = "type", window = iraq_window, time_col = "time", time_range = c(1, 60), coordinates = c("longitude", "latitude"), combine = FALSE) # Covariate surface: distance from Baghdad hfr$dist_bag <- rep(list(get_dist_focus(window = iraq_window, lon = 44.366, lat = 33.315, ndim = 64)), nrow(hfr)) # Observed density of the treatment (propensity score) obs <- get_obs_dens(hfr, dep_var = "airstrike", indep_var = "dist_bag", ndim = 64, window = iraq_window)
'get_policy()' learns a sequence of logistic stochastic policies by optimizing the value estimated by [get_policy_value()]. Policies are fitted sequentially from horizon one through the requested horizon. The user must state whether a larger or smaller outcome is preferred.
get_policy( data, outcome, treatment, propensity, time, unit, policy, horizon = 1L, order = 1L, direction = c("minimize", "maximize"), lower = -100, upper = 100, initial = NULL, stabilize = c("mixed", "normalize", "none"), fixed_prob = NULL, conf_level = 0.95, value_lower = -Inf, optimizer_control = list(), test_control = list(total_points = 100L, B = 1000L, alpha = 0.05, seed = NULL) )get_policy( data, outcome, treatment, propensity, time, unit, policy, horizon = 1L, order = 1L, direction = c("minimize", "maximize"), lower = -100, upper = 100, initial = NULL, stabilize = c("mixed", "normalize", "none"), fixed_prob = NULL, conf_level = 0.95, value_lower = -Inf, optimizer_control = list(), test_control = list(total_points = 100L, B = 1000L, alpha = 0.05, seed = NULL) )
data |
a data frame in long format with one row for every combination of time period and unit. It must be a complete time-by-unit data frame. It must contain the outcome, treatment, time, unit, and policy-predictor columns named in the other arguments. |
outcome |
a character string giving the name of the numeric outcome column in 'data'. Missing outcomes are allowed, but every evaluated time period must contain at least one observed outcome. |
treatment |
a character string giving the name of the treatment column in 'data'. The column must contain only 0 and 1. |
propensity |
the probability of each observed treatment assignment. Supply either the name of a numeric column in 'data', a numeric vector in the original row order of 'data', a matrix with one row per time period and one column per unit, or an object returned by [get_unit_ps()]. Every probability must be strictly between 0 and 1. |
time |
a character string giving the name of the time column in 'data'. |
unit |
a character string giving the name of the unit identifier column in 'data'. |
policy |
a one-sided formula such as '~ previous_treatment + x'. It defines the predictors in the logistic policy. Any histories or lagged variables used by the policy must already be columns in 'data'. |
horizon |
positive integer giving the largest policy horizon. |
order |
either 1, 2, or '"auto"'. Automatic selection compares the two linearizations with a multiplier-bootstrap test at each horizon. |
direction |
whether the policy should '"minimize"' or '"maximize"' the estimated outcome. |
lower |
lower bounds for the policy coefficients. Supply one number to use the same bound for every coefficient, or one number per coefficient. |
upper |
upper bounds for the policy coefficients. Supply one number to use the same bound for every coefficient, or one number per coefficient. |
initial |
optional initial coefficients. Supply a vector to reuse the same start at every stage, a matrix with one row per stage, or a list of stage-specific vectors. The default uses -1 for the intercept and 0 for other coefficients. |
stabilize |
the time-weight stabilization method passed to [get_policy_value()]. Choose '"mixed"', '"normalize"', or '"none"'. |
fixed_prob |
optional policy probabilities for units that should not be optimized. A named numeric vector can specify any subset of unit IDs. An unnamed vector must contain one probability for every unit. Values must be between 0 and 1. These fixed probabilities are used when optimizing and evaluating the learned policy. They are not used by the automatic order diagnostic, which compares the two estimators before unit-specific policy constraints are imposed. |
conf_level |
confidence level used for the normal approximation intervals returned with each fitted policy value. |
value_lower |
optional lower bound for every stage-specific value. A candidate below the bound receives a quadratic optimization penalty. |
optimizer_control |
list passed to [stats::optim()]. |
test_control |
list controlling 'order = "auto"': 'total_points' is the number of coefficient vectors used to compare the orders, 'B' is the number of multiplier-bootstrap draws, 'alpha' is the test level, and 'seed' controls reproducibility. |
At horizon 'm', coefficients learned for stages '1, ..., m - 1' remain fixed and only the new stage is optimized. The underlying logistic policy is 'plogis(X beta)'. This function does not construct histories automatically. Lagged treatments, outcomes, or covariates required by 'policy' should be created before calling the function.
The automatic order test evaluates both approximations at randomly selected coefficient vectors and uses time-level influence contributions to construct an integrated squared multiplier-bootstrap statistic. Increase 'total_points' and 'B' for final analyses. Small values are useful for quick checks.
An object of class 'policy_fit', containing: * 'coefficients': learned coefficient matrix. * 'value': one 'policy_value' object for each fitted horizon. * 'order' and 'order_test': selected linearization orders and test details. * 'convergence': optimizer codes and messages. * 'probability_summary': policy-probability summaries. Expected treatment rates by stage and unit are stored in each element of 'value'. * 'specification' and 'call': the fitted policy specification.
[get_policy_value()], [get_unit_ps()]
Other unit-level policy functions:
get_policy_value(),
get_unit_ps()
data <- expand.grid(time = 1:7, unit = letters[1:4]) data$x <- rep(seq(-1, 1, length.out = 4), 7) data$treatment <- rep(c(0, 1, 0, 1), 7) data$ps <- 0.5 data$outcome <- data$treatment + data$x + data$time / 10 fit <- get_policy( data = data, outcome = "outcome", treatment = "treatment", propensity = "ps", time = "time", unit = "unit", policy = ~ x, horizon = 2, order = 1, direction = "minimize", lower = -3, upper = 3, optimizer_control = list(maxit = 20) ) print(fit)data <- expand.grid(time = 1:7, unit = letters[1:4]) data$x <- rep(seq(-1, 1, length.out = 4), 7) data$treatment <- rep(c(0, 1, 0, 1), 7) data$ps <- 0.5 data$outcome <- data$treatment + data$x + data$time / 10 fit <- get_policy( data = data, outcome = "outcome", treatment = "treatment", propensity = "ps", time = "time", unit = "unit", policy = ~ x, horizon = 2, order = 1, direction = "minimize", lower = -3, upper = 3, optimizer_control = list(maxit = 20) ) print(fit)
'get_policy_value()' estimates the value of a stochastic policy for a complete time-by-unit data frame. It uses a first- or second-order linearized inverse-probability weight, allowing the number of units to be large without enumerating treatment assignments.
get_policy_value( data, outcome, treatment, propensity, time, unit, policy, policy_coef, order = 1L, stabilize = c("mixed", "normalize", "none"), fixed_prob = NULL, outcome_units = NULL, conf_level = 0.95, keep = c("standard", "all") )get_policy_value( data, outcome, treatment, propensity, time, unit, policy, policy_coef, order = 1L, stabilize = c("mixed", "normalize", "none"), fixed_prob = NULL, outcome_units = NULL, conf_level = 0.95, keep = c("standard", "all") )
data |
a data frame in long format with one row for every combination of time period and unit. It must be a complete time-by-unit data frame. It is not an array. |
outcome |
a character string giving the name of the numeric outcome column in 'data'. Missing outcomes are allowed, but every evaluated time period must contain at least one observed outcome. |
treatment |
a character string giving the name of the treatment column in 'data'. The column must contain only 0 and 1. |
propensity |
the probability of each observed treatment assignment. Supply either the name of a numeric column in 'data', a numeric vector in the original row order of 'data', a matrix with one row per time period and one column per unit, or an object returned by [get_unit_ps()]. Every probability must be strictly between 0 and 1. |
time |
a character string giving the name of the time column in 'data'. |
unit |
a character string giving the name of the unit identifier column in 'data'. |
policy |
a one-sided formula defining the policy design matrix. History or lagged variables must already be present in 'data'. |
policy_coef |
a numeric vector for a one-stage policy or a matrix with one row per policy stage. Named columns are matched to the columns produced by [stats::model.matrix()]. |
order |
order of the linearized inverse-probability weight, either 1 or 2. |
stabilize |
weight stabilization method: '"mixed"' reproduces the smooth mixture of normalized and recentered weights, '"normalize"' divides by the mean time weight, and '"none"' leaves weights unchanged. |
fixed_prob |
optional numeric vector of policy probabilities for units whose treatment probability is fixed. A named vector may contain a subset of units. An unnamed vector must contain one value per unit. |
outcome_units |
optional character vector of unit IDs whose outcomes should be averaged. Policy weights are still constructed from every unit. The default uses all units. This is useful for evaluating a learned policy for one unit or a group of units without changing the policy weights. |
conf_level |
confidence level for the normal approximation interval. |
keep |
amount of intermediate information to retain. '"standard"' omits unit likelihood ratios. '"all"' retains them for diagnostics and exact replication work. |
Let 'r' be the likelihood ratio for a unit: 'q / p' for a treated unit and '(1 - q) / (1 - p)' otherwise, where 'p' is its observed propensity and 'q' is its probability under the policy. With 'z = r - 1', the first-order time weight is '1 + sum(z)'. The second-order weight additionally includes every pair product and is evaluated as '0.5 * ((sum(z))^2 - sum(z^2))'.
For a multi-stage policy, row 1 of 'policy_coef' describes the latest stage and the last row describes the earliest stage in each evaluation window. Stage weights are multiplied recursively to represent the policy history.
An object of class 'policy_value', a list containing the overall and stage-specific values, variance and confidence interval, a 'unit_outcome' data frame with each unit's expected outcome and interval, expected treatment summaries by stage and unit, time-level influence contributions, policy probabilities, optional unit likelihood ratios, stabilized time weights, stabilization diagnostics, and the complete specification needed to interpret the estimate.
[get_unit_ps()], [get_policy()]
Other unit-level policy functions:
get_policy(),
get_unit_ps()
data <- expand.grid(time = 1:6, unit = letters[1:4]) data$x <- rep(seq(-1, 1, length.out = 4), 6) data$treatment <- rep(c(0, 1, 0, 1), 6) data$ps <- 0.5 data$outcome <- data$treatment + data$x + data$time / 10 value <- get_policy_value( data = data, outcome = "outcome", treatment = "treatment", propensity = "ps", time = "time", unit = "unit", policy = ~ x, policy_coef = c("(Intercept)" = 0, x = 0.5), order = 1 ) print(value)data <- expand.grid(time = 1:6, unit = letters[1:4]) data$x <- rep(seq(-1, 1, length.out = 4), 6) data$treatment <- rep(c(0, 1, 0, 1), 6) data$ps <- 0.5 data$outcome <- data$treatment + data$x + data$time / 10 value <- get_policy_value( data = data, outcome = "outcome", treatment = "treatment", propensity = "ps", time = "time", unit = "unit", policy = ~ x, policy_coef = c("(Intercept)" = 0, x = 0.5), order = 1 ) print(value)
'get_power_dens()' takes the target densities and their priorities and returns a power density.
get_power_dens(target_dens, priorities, window)get_power_dens(target_dens, priorities, window)
target_dens |
list of target densities |
priorities |
vector of priorities for each of target densities |
window |
owin object |
'get_power_dens()' raises each target density to the power given by the corresponding entry of 'priorities', multiplies the results together, and normalizes the product to integrate to one over 'window'. The resulting power density is used to shift the locations of counterfactual events relative to the baseline density.
an im object of power densities
Papadogeorgou, G., Imai, K., Lyall, J. and Li, F. (2022). Causal inference with spatio-temporal data: estimating the effects of airstrikes on insurgent violence in Iraq. Journal of the Royal Statistical Society Series B, 84(5), 1969–1999. doi:10.1111/rssb.12548
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
[get_cf_dens()], [sim_power_dens()]
Other density estimation functions:
get_adaptive_baseline_dens(),
get_base_dens(),
get_cf_dens(),
get_cf_dens_adaptive(),
get_cf_sum_log_intens(),
get_obs_dens(),
sim_cf_dens(),
sim_power_dens()
# A target density: proportional to the distance from Baghdad dist_baghdad <- get_dist_focus(window = iraq_window, lon = 44.366, lat = 33.315, ndim = 64) power <- get_power_dens(target_dens = list(dist_baghdad / sum(dist_baghdad)), priorities = 1, window = iraq_window)# A target density: proportional to the distance from Baghdad dist_baghdad <- get_dist_focus(window = iraq_window, lon = 44.366, lat = 33.315, ndim = 64) power <- get_power_dens(target_dens = list(dist_baghdad / sum(dist_baghdad)), priorities = 1, window = iraq_window)
'get_sens()' computes bounds on the causal contrast between two counterfactual densities across a grid of sensitivity parameters 'gamma'. At each value of 'gamma', linear programming is used to obtain worst-case upper and lower bounds of the Hajek-weighted estimand for each scenario; the returned bounds describe how robust the causal contrast is to possible violations of the no-unmeasured-confounding assumption.
get_sens( obs, cf1, cf2, treat, sm_out, lag, entire_window, window, gamma_vals = seq(1, 1.2, by = 0.01), time_after = TRUE, trunc_level = NA, tol_slack = 1e-06, grid_init = 15, max_refine = 5 )get_sens( obs, cf1, cf2, treat, sm_out, lag, entire_window, window, gamma_vals = seq(1, 1.2, by = 0.01), time_after = TRUE, trunc_level = NA, tol_slack = 1e-06, grid_init = 15, max_refine = 5 )
obs |
observed density |
cf1 |
counterfactual density 1 |
cf2 |
counterfactual density 2 |
treat |
column of a hyperframe that summarizes treatment data. In the form of 'hyperframe$column'. |
sm_out |
column of a hyperframe that summarizes the smoothed outcome data |
lag |
integer that specifies lags to calculate causal estimates |
entire_window |
owin object (the entire region of interest) |
window |
owin object (the sub-window over which the contrast is evaluated) |
gamma_vals |
numeric vector of sensitivity parameters (>= 1) at which to compute bounds. By default, 'seq(1, 1.2, by = 0.01)'. |
time_after |
whether to include one unit time difference between treatment and outcome. By default = TRUE |
trunc_level |
the level of truncation for the weights (0-1) |
tol_slack |
numeric tolerance used to determine whether zero is attainable. Default is '1e-6'. |
grid_init |
number of grid points used in each adaptive lambda search step. Default is 15. |
max_refine |
maximum number of adaptive lambda refinement steps. Default is 5. |
'gamma = 1' corresponds to no unmeasured confounding and recovers point estimates analogous to those of 'get_est()'. As 'gamma' increases, the bounds widen, reflecting greater allowance for unobserved confounding. The 'lb' and 'ub' columns retain the conservative bounds from the original implementation. The 'zero_attainable' column indicates whether the result is no longer robust under the current value of 'gamma', or equivalently under the current allowance for unmeasured confounding. The underlying linear programs are solved with 'Rglpk::Rglpk_solve_LP()'.
This function performs its computation using the 'future' framework (via 'furrr'); to run it in parallel, set 'future::plan(future::multisession)' before calling this function. The results are identical regardless of the plan.
a tibble with columns: * 'gamma': the sensitivity parameter * 'lb': lower bound on the causal contrast at 'gamma' * 'ub': upper bound on the causal contrast at 'gamma' * 'zero_attainable': whether zero is attainable at 'gamma' * 'robust_gamma': the largest gamma at which zero is not attainable
Papadogeorgou, G., Imai, K., Lyall, J. and Li, F. (2022). Causal inference with spatio-temporal data: estimating the effects of airstrikes on insurgent violence in Iraq. Journal of the Royal Statistical Society Series B, 84(5), 1969–1999. doi:10.1111/rssb.12548
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
Other sensitivity analysis functions:
get_cate_sens()
'get_unit_ps()' estimates treatment probabilities for a complete time-by-unit data frame of discrete spatial or administrative units. It supports a pooled logistic regression and, when 'geepack' is installed, a generalized estimating equation (GEE). The returned object also contains inverse-probability weights and standardized-difference balance diagnostics.
get_unit_ps( formula, data, time, unit, engine = c("glm", "gee"), cluster = NULL, clip = c(0.01, 0.99), balance = NULL, ... )get_unit_ps( formula, data, time, unit, engine = c("glm", "gee"), cluster = NULL, clip = c(0.01, 0.99), balance = NULL, ... )
formula |
a two-sided model formula. The left-hand side must be the name of a binary treatment column in 'data'. The right-hand side lists the covariates used to estimate the treatment probability. |
data |
a data frame in long format with one row for every combination of time period and unit. It must be a complete time-by-unit data frame. It is not an array. |
time |
a character string giving the name of the time column in 'data'. |
unit |
a character string giving the name of the unit identifier column in 'data'. |
engine |
estimation engine: '"glm"' (the default) or '"gee"'. |
cluster |
character string naming the GEE cluster column. If 'NULL', 'time' is used. Ignored when 'engine = "glm"'. |
clip |
numeric vector of length two giving the lower and upper bounds applied to fitted treatment probabilities. |
balance |
optional character vector naming variables for which absolute standardized differences should be computed. By default, variables used in 'formula' are included. |
... |
additional arguments passed to [stats::glm()] or [geepack::geeglm()]. |
The input must be balanced and uniquely indexed by 'time' and 'unit'. Numeric balance variables are compared using standardized mean differences. Factors and character variables are expanded into level indicators whose labels appear in the 'variable' column, such as 'region: north'.
An object of class 'unit_ps', a list containing: * 'model': fitted propensity-score model. * 'fitted': clipped probabilities in time-unit order. * 'propensity': a time by unit probability matrix. * 'observed_weight': inverse probability of the observed treatment. * 'balance': tidy unweighted and weighted balance diagnostics. * 'data_info' and 'call': model metadata.
[get_policy_value()], [get_policy()]
Other unit-level policy functions:
get_policy(),
get_policy_value()
data <- expand.grid(time = 1:5, unit = letters[1:4]) data$x <- rep(seq(-1, 1, length.out = 4), 5) data$treatment <- as.integer(data$x + data$time / 10 > 0) ps <- get_unit_ps(treatment ~ x, data, time = "time", unit = "unit") print(ps) plot(ps, type = "overlap")data <- expand.grid(time = 1:5, unit = letters[1:4]) data$x <- rep(seq(-1, 1, length.out = 4), 5) data$treatment <- as.integer(data$x + data$time / 10 > 0) ps <- get_unit_ps(treatment ~ x, data, time = "time", unit = "unit") print(ps) plot(ps, type = "overlap")
A function that calculates variance upper bounds
get_var_bound(estimates)get_var_bound(estimates)
estimates |
an object returned from 'get_est()' function |
'get_var_bound()' is an internal function to 'get_estimates()' function, performing the estimation analysis after 'get_est()' function.
list of variance upper bounds for each scenario ('bound_haj') and causal contrasts ('bound_tau_haj'). Note that this function returns variance upper bounds for Hajek estimators
Papadogeorgou, G., Imai, K., Lyall, J. and Li, F. (2022). Causal inference with spatio-temporal data: estimating the effects of airstrikes on insurgent violence in Iraq. Journal of the Royal Statistical Society Series B, 84(5), 1969–1999. doi:10.1111/rssb.12548
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
Other causal effect estimation functions:
get_cate(),
get_est(),
get_estimates(),
get_weighted_surf()
A function that returns averaged weighted surfaces (both IPW and Hajek) along with weights
get_weighted_surf( obs_dens, cf_dens, mediation = FALSE, cate = FALSE, obs_med_log_sum_dens, cf_med_log_sum_dens, treatment_data, smoothed_outcome, lag, entire_window, time_after, truncation_level = truncation_level )get_weighted_surf( obs_dens, cf_dens, mediation = FALSE, cate = FALSE, obs_med_log_sum_dens, cf_med_log_sum_dens, treatment_data, smoothed_outcome, lag, entire_window, time_after, truncation_level = truncation_level )
obs_dens |
observed density |
cf_dens |
counterfactual density |
mediation |
whether to perform causal mediation analysis. By default, FALSE. |
cate |
whether to perform the heterogeneity analysis. By default, FALSE. |
obs_med_log_sum_dens |
sum of log densities of mediators for the observed (if 'mediation = TRUE') |
cf_med_log_sum_dens |
sum of log densities of mediators for counterfactual (if 'mediation = TRUE') |
treatment_data |
column of a hyperframe that summarizes treatment data. In the form of 'hyperframe$column'. |
smoothed_outcome |
column of a hyperframe that summarizes the smoothed outcome data |
lag |
integer that specifies lags to calculate causal estimates |
entire_window |
owin object (the entire region of interest) |
time_after |
whether to include one unit time difference between treatment and outcome |
truncation_level |
the level at which the weights are truncated (see 'get_estimates()') |
'get_weighted_surf()' is an internal function to 'get_estimates()' function. If 'time_after' is TRUE, then this function uses treatment data and weights from lag to nrow(data)-1, and outcome data from lag+1 to nrow(data).
This function performs its computation using the 'future' framework (via 'furrr'); to run it in parallel, set 'future::plan(future::multisession)' before calling this function. The results are identical regardless of the plan.
list of an average weighted surface ('avarage_surf', an 'im' object), a Hajek average weighted surface ('average_weighted_surf_haj', an 'im' object), weights, and smoothed outcomes
Papadogeorgou, G., Imai, K., Lyall, J. and Li, F. (2022). Causal inference with spatio-temporal data: estimating the effects of airstrikes on insurgent violence in Iraq. Journal of the Royal Statistical Society Series B, 84(5), 1969–1999. doi:10.1111/rssb.12548
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
Other causal effect estimation functions:
get_cate(),
get_est(),
get_estimates(),
get_var_bound()
'get_window()' takes a directory that hosts a shapefile and returns an owin object.
get_window(load_path, target_crs = NULL, unit_scale = 1000)get_window(load_path, target_crs = NULL, unit_scale = 1000)
load_path |
path to the shp file |
target_crs |
target CRS (if users want to specify it; as an EPSG code) |
unit_scale |
parameter to convert meters to kilometers (by default = 1000 so that the unit is set to km) |
'get_window()' reads a shapefile and converts its boundary into a 'spatstat.geom::owin' object. When 'target_crs' is not supplied and the data are in longitude/latitude, a Cartesian CRS is suggested automatically via 'crsuggest::suggest_crs()' and the geometry is projected accordingly. Polygon vertices are reordered to anti-clockwise as required by 'owin', the window is rescaled by 'unit_scale' (so the default unit becomes kilometers), and the CRS is stored as an attribute for downstream functions.
owin object
[get_hfr()]
Other spatial utility functions:
conv_owin_into_sf(),
get_dist_focus(),
get_dist_line(),
get_distexp(),
get_elev()
# An example window from the shapefile shipped with the sf package win <- get_window(load_path = system.file("shape/nc.shp", package = "sf"), target_crs = 32119)# An example window from the shapefile shipped with the sf package win <- get_window(load_path = system.file("shape/nc.shp", package = "sf"), target_crs = 32119)
'imls_to_arr()' convert a list of im object to a 3D array
imls_to_arr(imls, start = 1, end = NULL, entire_window = NULL, ...)imls_to_arr(imls, start = 1, end = NULL, entire_window = NULL, ...)
imls |
a list of im objects (imlist) |
start |
the index of the first im to be converted. Default is 1. |
end |
the index of the last im to be converted. If not provided, then it will be set to the length of the list. |
entire_window |
a owin object. If given, then the values outside the region will be set to 'NA'. |
... |
Additional arguments passed to spatstat conversion functions. |
'imls_to_arr()' is a internal function for 'imls_to_vec()'. By default, it returns a three-dimensional array of dimension by by where and
are the dimensions of the im objects, and is the length of the list. All the im objects in the list need to have the same dimensions.
a three-dimensional array of dimension by by ,
where and are the pixel dimensions of the 'im' objects and
is the number of selected list elements. When 'entire_window' is
supplied, cells outside that window are set to 'NA'.
Other data preparation functions:
get_em_vec(),
get_hfr(),
get_hist(),
pixel_count_ppp(),
smooth_ppp()
A dataset of insurgencies data in Iraq (February to July 2007)
insurgenciesinsurgencies
A tibble with 68573 rows and 4 variables:
Date (YYYY-MM-DD)
Longitudes (decimal)
Latitudees (decimal)
Types of insurgencies (improvised explosive devices (IED), small arms fire (SAF), or other)
insurgenciesinsurgencies
A dataset of insurgencies data in Iraq in 2006 (2006/1/1-2006/9/24)
insurgencies_2006insurgencies_2006
A tibble with 37701 rows and 4 variables:
Date (YYYY-MM-DD)
Longitudes (decimal)
Latitudees (decimal)
Types of insurgencies (improvised explosive devices (IED), small arms fire (SAF), or other)
insurgencies_2006insurgencies_2006
An owin object of Iraq
iraq_windowiraq_window
A polygonal object:
Polygonal
Range (longitude)
Range (latitude)
Boundaries
Units
iraq_windowiraq_window
'pixel_count_ppp()' takes a column of hyperframes (ppp objects) and gets the number of events in each pixel.
pixel_count_ppp( data, resolution = NULL, ndim = NULL, W = NULL, weights = NULL, DivideByPixelArea = FALSE, ... )pixel_count_ppp( data, resolution = NULL, ndim = NULL, W = NULL, weights = NULL, DivideByPixelArea = FALSE, ... )
data |
the name of a hyperframe and column of interest. |
resolution |
resolution of raster (distance map) (in km) |
ndim |
the number of dimensions of grid cells (ndim^2). Users need to set either resolution or ndim. |
W |
Optional window mask (object of class '"owin"') determining the pixel raster. 'data' should be in the form of '"hyperframe$column"'. |
weights |
Optional vector of weights associated with the points. |
DivideByPixelArea |
Logical value determining whether the resulting pixel values should be devided by the pixel area. Default value is 'False'. |
... |
parameters passed on to the function. |
This function performs its computation using the 'future' framework (via 'furrr'); to run it in parallel, set 'future::plan(future::multisession)' before calling this function. The results are identical regardless of the plan.
im objects
Other data preparation functions:
get_em_vec(),
get_hfr(),
get_hist(),
imls_to_arr(),
smooth_ppp()
# Time variable dat_out <- insurgencies[1:100, ] dat_out$time <- as.numeric(dat_out$date - min(dat_out$date) + 1) # Hyperframe dat_hfr <- get_hfr(data = dat_out, col = "type", window = iraq_window, time_col = "time", time_range = c(1, max(dat_out$time)), coordinates = c("longitude", "latitude"), combine = TRUE) # Get the number of events for each pixel pixel_count_ppp(data = dat_hfr$all_combined)# Time variable dat_out <- insurgencies[1:100, ] dat_out$time <- as.numeric(dat_out$date - min(dat_out$date) + 1) # Hyperframe dat_hfr <- get_hfr(data = dat_out, col = "type", window = iraq_window, time_col = "time", time_range = c(1, max(dat_out$time)), coordinates = c("longitude", "latitude"), combine = TRUE) # Get the number of events for each pixel pixel_count_ppp(data = dat_hfr$all_combined)
Plot method for objects of class 'cate', returned by [get_cate()]. Visualizes the estimated conditional average treatment effects (CATE) across the chosen evaluation values, or the estimated regression coefficients, with confidence intervals.
## S3 method for class 'cate' plot( x, ..., result = "cate", type = "l", scale = 1, xrange = NULL, main = "", xlab = "", ylim = NULL )## S3 method for class 'cate' plot( x, ..., result = "cate", type = "l", scale = 1, xrange = NULL, main = "", xlab = "", ylim = NULL )
x |
an object of class 'cate', typically the output of [get_cate()]. |
... |
additional arguments. Currently ignored. |
result |
specify which values will be used for plot. Default is "cate" - If 'result' is "cate", then estimated cate values will be used - If 'result' is "beta", then the estimated regression coefficients will be used |
type |
The type of plot to draw. This argument will be ignored if 'result' = "beta". Default is "l". - If 'type' is "p", points with error bars will be drawn. - If 'type' is "l", lines with shaded region will be drawn. - If 'type' is a vector of strings, each element specifies the type for the corresponding 'eval_values' value. |
scale |
a positive number specifying the scale by which the estimates will be scaled. If provided, the estimates will be scaled by this value. Default is NULL, which means no scaling is applied. |
xrange |
an optional vector of two values the range of x shown. |
main |
title |
xlab |
label of x-axis |
ylim |
an optional vector of two values specifying the limits of y |
A 'ggplot' object showing the estimated CATE (or regression coefficients) with confidence intervals.
[get_cate()]
Plot method for objects of class 'cflist', returned by [sim_cf_dens()]. Takes the simulated counterfactual densities and their powers and returns a faceted counterfactual density image over the range of parameters.
## S3 method for class 'cflist' plot( x, ..., color = c("white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", "#771F59FF"), grayscale = FALSE )## S3 method for class 'cflist' plot( x, ..., color = c("white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", "#771F59FF"), grayscale = FALSE )
x |
an object of class 'cflist', typically the output of [sim_cf_dens()]. |
... |
additional arguments. Currently ignored. |
color |
the color scale. By default, "white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", and "#771F59FF". |
grayscale |
logical. 'grayscale' specifies whether to convert plot to grayscale (by default, FALSE). |
A 'ggplot' object (a faceted arrangement of counterfactual density images, one per power).
[sim_cf_dens()]
Plot method for objects of class 'distlist', returned by [get_distexp()]. Visualizes the expected number (or proportion) of treatment events covered as a function of distance from the focus, and optionally the windows defined by distance quantiles.
## S3 method for class 'distlist' plot( x, ..., dist_map_unit = "km", grayscale = FALSE, win_plot = FALSE, use_raw = FALSE )## S3 method for class 'distlist' plot( x, ..., dist_map_unit = "km", grayscale = FALSE, win_plot = FALSE, use_raw = FALSE )
x |
an object of class 'distlist', typically the output of [get_distexp()]. |
... |
additional arguments. Currently ignored. |
dist_map_unit |
either '"km"' or '"mile"' |
grayscale |
grayscale or not. By default, FALSE. |
win_plot |
whether to plot windows as well. By default, FALSE |
use_raw |
logical. 'use_raw' specifies whether to use the raw value of expectations or percentiles. By default, 'FALSE'. |
A 'ggplot' object. If 'win_plot = TRUE', the arranged window plots; otherwise the expectation-versus-distance plot.
[get_distexp()]
Plot method for objects of class 'est', returned by [get_est()]. Visualizes the estimated causal effects per time period (point estimates with 90 weighted counterfactual density surfaces.
## S3 method for class 'est' plot(x, ..., surface = FALSE, lim = NA)## S3 method for class 'est' plot(x, ..., surface = FALSE, lim = NA)
x |
an object of class 'est', typically the output of [get_est()]. |
... |
additional arguments. Currently ignored. |
surface |
whether to produce the surface plot. By default, FALSE |
lim |
limits of the scale. By default, NA. To set limits manually, provide a vector of max and min |
If 'surface = FALSE' (the default), a single 'ggplot' object showing the causal effects per time period. If 'surface = TRUE', a named list with two 'ggplot' objects, 'surface' (the difference in average weighted surfaces) and 'expectation' (the causal effects per time period).
[get_est()]
Plot method for objects of class 'hyperframe' (as created by [get_hfr()]). Visualizes the selected point pattern ('ppp') or pixel image ('im') column(s) over the specified time period(s), arranging multiple time periods and/or columns by faceting or combining them.
## S3 method for class 'hyperframe' plot( x, ..., col, time_col = "time", range, lim = NA, main = "Image object", scalename = NA, color = c("white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", "#771F59FF"), combined = TRUE )## S3 method for class 'hyperframe' plot( x, ..., col, time_col = "time", range, lim = NA, main = "Image object", scalename = NA, color = c("white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", "#771F59FF"), combined = TRUE )
x |
an object of class 'hyperframe', typically the output of [get_hfr()]. |
... |
additional arguments. Currently ignored. |
col |
the name/s of a column of interest. |
time_col |
The name of the column of time variable. By default, '"time"'. Note that the time variable must be integers. |
range |
vector that specifies the range of tiem variable (e.g., 'c("2007-01-01", "2007-01-31")') |
lim |
limits of the scale. By default, NA. To set limits manually, provide a vector or max and min |
main |
title To specify multiple columns, users should list column names as a character vector. |
scalename |
the name of the scale (for images only) |
color |
the color scale. By default, "white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", and "#771F59FF". |
combined |
logical. 'combined' specifies whether to combine all the point processes to one plot. This argument applies only to the case when users specify one column with multiple time periods. By default = TRUE |
A 'ggplot' object visualizing the selected column(s) and time period(s).
[get_hfr()]
Plot method for objects of class 'im' (spatstat pixel images, such as the density images produced by the package's density functions). Renders the image as a filled raster over its observation window, with optional value transformation and grayscale rendering.
## S3 method for class 'im' plot( x, ..., main = "Image object", scalename = "Density", grayscale = "FALSE", transf = NULL, color = c("white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", "#771F59FF"), lim = NA )## S3 method for class 'im' plot( x, ..., main = "Image object", scalename = "Density", grayscale = "FALSE", transf = NULL, color = c("white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", "#771F59FF"), lim = NA )
x |
an object of class 'im' (a spatstat pixel image), for example a density image produced by a 'get_*_dens()' function. |
... |
additional arguments. Currently ignored. |
main |
title |
scalename |
the name of the scale (for images only) |
grayscale |
whether to use grayscale. By default, FALSE. |
transf |
a function to transform the pixel values (by default, NULL) |
color |
the color scale. By default, "white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", and "#771F59FF". |
lim |
limits of the scale. By default, NA. To set limits manually, provide a vector or max and min |
A 'ggplot' object rendering the pixel image.
Plot method for objects of class 'imlist' (a list of spatstat pixel images, such as a sequence of density images over time periods). Renders one or more images as filled rasters over their observation window, arranging multiple frames into a common-legend grid.
## S3 method for class 'imlist' plot( x, ..., main = "image", lim = NA, transf = NULL, frame = 1, scalename = "Density", color = c("white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", "#771F59FF"), grayscale = FALSE, ncol = NA, nrow = NA )## S3 method for class 'imlist' plot( x, ..., main = "image", lim = NA, transf = NULL, frame = 1, scalename = "Density", color = c("white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", "#771F59FF"), grayscale = FALSE, ncol = NA, nrow = NA )
x |
an object of class 'imlist' (a list of spatstat pixel images), for example a sequence of density images produced by a 'get_*_dens()' function. |
... |
additional arguments. Currently ignored. |
main |
title |
lim |
limits of the scale. By default, NA. To set limits manually, provide a vector or max and min |
transf |
a function to transform the pixel values (by default, NULL) |
frame |
the element number of the list object (by default, 1) |
scalename |
the name of the scale |
color |
the color scale. By default, "white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", and "#771F59FF". |
grayscale |
grayscale or not. By default, FALSE. |
ncol |
the number of columns (if plotitng multiple images at once) |
nrow |
the number of rows (if plotting multiple images at once) |
A 'ggplot' object. For a single frame, the rendered image; for multiple frames, an arranged grid of images with a common legend.
Plot method for objects of class 'list'. If the list contains spatstat pixel images ('im'), they are rendered as filled rasters; if it contains point patterns ('ppp'), the points are plotted over the observation window. Multiple frames are arranged into a grid (images) or combined/faceted (point patterns).
## S3 method for class 'list' plot( x, ..., main = "list", lim = NA, transf = NULL, frame = 1, combined = TRUE, scalename = "Density", color = c("white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", "#771F59FF"), grayscale = FALSE, ncol = NA, nrow = NA )## S3 method for class 'list' plot( x, ..., main = "list", lim = NA, transf = NULL, frame = 1, combined = TRUE, scalename = "Density", color = c("white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", "#771F59FF"), grayscale = FALSE, ncol = NA, nrow = NA )
x |
a 'list' of spatstat pixel images ('im') or point patterns ('ppp'). |
... |
additional arguments. Currently ignored. |
main |
title |
lim |
limits of the scale. By default, NA. To set limits manually, provide a vector or max and min |
transf |
a function to transform the pixel values (by default, NULL) |
frame |
the element number of the list object (by default, 1) |
combined |
logical. 'combined' specifies whether to combine all the point processes to one plot. This argument applies only to point-pattern lists with multiple time periods. By default = TRUE |
scalename |
the name of the scale |
color |
the color scale. By default, "white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", and "#771F59FF". |
grayscale |
grayscale or not. By default, FALSE. |
ncol |
the number of columns (if plotitng multiple images at once) |
nrow |
the number of rows (if plotting multiple images at once) |
A 'ggplot' object visualizing the images or point patterns in the list.
Plot method for objects of class 'obs', returned by [get_obs_dens()]. Compares actual versus predicted event counts over time, shows the corresponding residuals, and maps the average residual field. Up to three fitted densities can be overlaid for comparison.
## S3 method for class 'obs' plot( x, ..., dens_2 = NA, dens_3 = NA, lim = c(-1, 1), time_unit = NA, combined = TRUE, color_actual = "darkgrey", color_dens_1 = "#f68f46ff", color_dens_2 = "#593d9cff", color_dens_3 = "#efe350ff" )## S3 method for class 'obs' plot( x, ..., dens_2 = NA, dens_3 = NA, lim = c(-1, 1), time_unit = NA, combined = TRUE, color_actual = "darkgrey", color_dens_1 = "#f68f46ff", color_dens_2 = "#593d9cff", color_dens_3 = "#efe350ff" )
x |
an object of class 'obs', typically the output of [get_obs_dens()]. |
... |
additional arguments. Currently ignored. |
dens_2 |
density 2 (if any). By default, 'NA'. |
dens_3 |
density 3 (if any). By default, 'NA'. |
lim |
limits of the scale for the average residual fields. By default, c(0, -1). To set limits manually, provide a vector of max and min |
time_unit |
x-axis label of the output |
combined |
whether to combine the two plots. By default, TRUE. If TRUE, then the plot function produces one ggplot object. If FALSE, three objects (two ggplot and one dataframe) will be produced. |
color_actual |
name of the color for the actual density |
color_dens_1 |
name of the color for the predicted density |
color_dens_2 |
name of the color for another predicted density (usually for the out-of-sample prediction) |
color_dens_3 |
another color for an alternate density for out-of-sample prediction |
If 'combined = TRUE' (the default), a single arranged 'ggplot' object combining the comparison, residual, and (when applicable) average-residual-field panels. If 'combined = FALSE', a named list with the underlying data frame ('plot_data') and the individual 'ggplot' objects ('plot_compare', 'plot_residual', 'plot_arf').
[get_obs_dens()]
Plot method for objects of class 'powerlist', returned by [sim_power_dens()]. Takes the simulated power densities and their priorities and returns a faceted power density image over the range of parameters.
## S3 method for class 'powerlist' plot( x, ..., color = c("white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", "#771F59FF"), grayscale = FALSE )## S3 method for class 'powerlist' plot( x, ..., color = c("white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", "#771F59FF"), grayscale = FALSE )
x |
an object of class 'powerlist', typically the output of [sim_power_dens()]. |
... |
additional arguments. Currently ignored. |
color |
the color scale. By default, "white", "#F8DAC5FF", "#F4825AFF", "#D2204CFF", and "#771F59FF". |
grayscale |
logical. 'grayscale' specifies whether to convert plot to grayscale (by default, FALSE). |
A 'ggplot' object (a faceted arrangement of power density images).
[sim_power_dens()]
Plot method for objects of class 'ppplist' (a list of spatstat point patterns, such as observed events across time periods). Plots the points over the observation window, either combining multiple time periods into one plot or faceting them.
## S3 method for class 'ppplist' plot(x, ..., frame = 1, main = "ppp", combined = TRUE)## S3 method for class 'ppplist' plot(x, ..., frame = 1, main = "ppp", combined = TRUE)
x |
an object of class 'ppplist' (a list of spatstat point patterns). |
... |
additional arguments. Currently ignored. |
frame |
the element number of the list object (by default, 1) |
main |
title |
combined |
logical. 'combined' specifies whether to combine all the point processes to one plot. This argument applies only to the case when users specify one column with multiple time periods. By default = TRUE |
A 'ggplot' object plotting the selected point pattern(s).
Plot method for objects of class 'supthin', returned by [dx_supthin()]. Visualizes the observed and simulated-envelope summary functions (the K-function and the centered L-function) used to diagnose departures from complete spatial randomness after superthinning.
## S3 method for class 'supthin' plot(x, ...)## S3 method for class 'supthin' plot(x, ...)
x |
an object of class 'supthin', typically the output of [dx_supthin()]. |
... |
additional arguments. Currently ignored. |
A named list with two 'ggplot' objects, 'plot_k' (the K-function with simulation envelope) and 'plot_l' (the centered L-function with simulation envelope).
[dx_supthin()]
Plot unit-level propensity scores and balance
## S3 method for class 'unit_ps' plot(x, type = c("overlap", "balance"), ...)## S3 method for class 'unit_ps' plot(x, type = c("overlap", "balance"), ...)
x |
an object returned by [get_unit_ps()]. |
type |
plot type: '"overlap"' displays propensity-score distributions by observed treatment, and '"balance"' displays absolute standardized differences before and after weighting. |
... |
additional arguments. Currently ignored. |
A 'ggplot' object.
[get_unit_ps()]
Plot method for objects of class 'weights', derived from the estimation produced by [get_est()]. Displays histograms of the (standardized or unstandardized) inverse-probability weights, faceted by intervention.
## S3 method for class 'weights' plot(x, ..., type_weights = "standardized", binwidth = NULL)## S3 method for class 'weights' plot(x, ..., type_weights = "standardized", binwidth = NULL)
x |
an object of class 'weights', derived from the output of [get_est()]. |
... |
additional arguments. Currently ignored. |
type_weights |
the type of weights to plot. - If 'plot_weights' is 'standardized', histogram of standardized weights will be generated. - If 'plot_weights' is 'unstandardized', histogram of unstandardized weights will be generated. Default is 'standardized'. |
binwidth |
bin width of the histogram. Default is NULL |
A 'ggplot' object showing histograms of the weights, faceted by intervention.
[get_est()]
Print method for objects of class 'cate', returned by [get_cate()]. Builds and returns a data frame of the estimated CATE values at the chosen evaluation points, together with their 90
## S3 method for class 'cate' print(x, ...)## S3 method for class 'cate' print(x, ...)
x |
an object of class 'cate', typically the output of [get_cate()]. |
... |
additional arguments. Currently ignored. |
Currently, observed densities (class: obs), estimates (class: est) and heterogeneity estimates (class: cate) are supported by this function.
A data frame with one row per evaluation value, containing the evaluation value, the point estimate, and the lower/upper bounds of the 90 and 95
[get_cate()]
Print method for objects of class 'est', returned by [get_est()]. Builds and returns a data frame of the estimated causal effects per time period, together with their 90
## S3 method for class 'est' print(x, ...)## S3 method for class 'est' print(x, ...)
x |
an object of class 'est', typically the output of [get_est()]. |
... |
additional arguments. Currently ignored. |
Currently, observed densities (class: obs) and estimates (class: est) are supported by this function.
A data frame with one row per window, containing the point estimate and the lower/upper bounds of the 90
[get_est()]
Print a learned unit-level policy
## S3 method for class 'policy_fit' print(x, ...)## S3 method for class 'policy_fit' print(x, ...)
x |
an object returned by [get_policy()]. |
... |
additional arguments. Currently ignored. |
A data frame containing the selected order, expected outcome, confidence interval, and expected treatment rate at each fitted horizon.
[get_policy()]
Print a unit-level policy value
## S3 method for class 'policy_value' print(x, ...)## S3 method for class 'policy_value' print(x, ...)
x |
an object returned by [get_policy_value()]. |
... |
additional arguments. Currently ignored. |
A one-row data frame with the expected outcome, its standard error and confidence interval, and the expected treatment rate.
[get_policy_value()]
Print a unit-level propensity-score model
## S3 method for class 'unit_ps' print(x, ...)## S3 method for class 'unit_ps' print(x, ...)
x |
an object returned by [get_unit_ps()]. |
... |
additional arguments. Currently ignored. |
A one-row data frame summarizing the engine, data dimensions, and probability range.
[get_unit_ps()]
A variant of 'get_weighted_surf()' that retains per-period Hajek weights for both the entire region and a window of interest, so that downstream linear-programming bounds can be computed.
sens_weighted_surf( obs_dens, cf_dens, treatment_data, smoothed_outcome, lag, entire_window, window, time_after, truncation_level = 0.95 )sens_weighted_surf( obs_dens, cf_dens, treatment_data, smoothed_outcome, lag, entire_window, window, time_after, truncation_level = 0.95 )
obs_dens |
observed density |
cf_dens |
counterfactual density |
treatment_data |
column of a hyperframe that summarizes treatment data. In the form of 'hyperframe$column'. |
smoothed_outcome |
column of a hyperframe that summarizes the smoothed outcome data |
lag |
integer that specifies lags to calculate causal estimates |
entire_window |
owin object (the entire region of interest) |
window |
owin object (the sub-window of interest for which bounds are computed) |
time_after |
whether to include one unit time difference between treatment and outcome |
truncation_level |
the level at which the weights are truncated (see 'get_estimates()') |
'sens_weighted_surf()' is an internal function used by 'get_sens()'.
list of the following: * 'haj_wt_daily_out': Hajek-weighted daily outcomes integrated over the window of interest * 'haj_weights_window_of_interest': per-period Hajek weights for the window of interest * 'haj_weights_entire_window': per-period Hajek weights for the entire window
'sim_cf_dens()' takes a list of power densities and returns simulated counterfactual densities.
sim_cf_dens(expected_number, base_dens, power_sim_results, window)sim_cf_dens(expected_number, base_dens, power_sim_results, window)
expected_number |
the expected number of observations |
base_dens |
the baseline density (im object) |
power_sim_results |
the results obtained by 'simulate_power_density()' |
window |
owin object |
'sim_cf_dens()' combines a baseline density with each of the power densities produced by 'sim_power_dens()'. For every simulated set of priorities, the baseline density is multiplied by the corresponding power density, normalized over 'window', and rescaled to the supplied 'expected_number' of events. The result is a 'cflist' object holding the list of counterfactual densities together with the associated powers and expected number.
list of counterfactual densities, power as numerics, and expected number as a numeric
Papadogeorgou, G., Imai, K., Lyall, J. and Li, F. (2022). Causal inference with spatio-temporal data: estimating the effects of airstrikes on insurgent violence in Iraq. Journal of the Royal Statistical Society Series B, 84(5), 1969–1999. doi:10.1111/rssb.12548
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
[sim_power_dens()], [get_distexp()]
Other density estimation functions:
get_adaptive_baseline_dens(),
get_base_dens(),
get_cf_dens(),
get_cf_dens_adaptive(),
get_cf_sum_log_intens(),
get_obs_dens(),
get_power_dens(),
sim_power_dens()
A function that takes the target densities and their priorities and returns a power density image over a range of parameters
sim_power_dens(target_dens, dens_manip, priorities, priorities_manip, window)sim_power_dens(target_dens, dens_manip, priorities, priorities_manip, window)
target_dens |
list of target densities. This should always be a list, even if there is only one target density. |
dens_manip |
a target density for which we manipulate the value of priorities |
priorities |
numeric. 'priorities' specifies the priority for the target density that we do not manipulate. |
priorities_manip |
vector of priorities for the density that we manipulate. |
window |
owin object |
'sim_power_dens()' generates a sequence of power densities by holding the priorities of the fixed target densities at 'priorities' while varying the priority of 'dens_manip' across the values in 'priorities_manip'. For each such value, the product of the powered target densities is normalized over 'window'. The result is a 'powerlist' object containing the list of power densities and the manipulated priorities, and is typically passed to 'sim_cf_dens()'.
list of densities and priorities
Papadogeorgou, G., Imai, K., Lyall, J. and Li, F. (2022). Causal inference with spatio-temporal data: estimating the effects of airstrikes on insurgent violence in Iraq. Journal of the Royal Statistical Society Series B, 84(5), 1969–1999. doi:10.1111/rssb.12548
Mukaigawara, M., Imai, K., Lyall, J. and Papadogeorgou, G. (2025). Spatiotemporal causal inference with arbitrary spillover and carryover effects. arXiv preprint. doi:10.48550/arXiv.2504.03464
Other density estimation functions:
get_adaptive_baseline_dens(),
get_base_dens(),
get_cf_dens(),
get_cf_dens_adaptive(),
get_cf_sum_log_intens(),
get_obs_dens(),
get_power_dens(),
sim_cf_dens()
'smooth_ppp()' takes a column of hyperframes (ppp objects) and smoothes them.
smooth_ppp( data, method, sampling = NA, resolution = NULL, ndim = NULL, ngroups = NULL )smooth_ppp( data, method, sampling = NA, resolution = NULL, ndim = NULL, ngroups = NULL )
data |
the name of a hyperframe and column of interest. 'data' should be in the form of '"hyperframe$column"'. |
method |
methods for smoothing ppp objects. Either '"mclust"' or '"abramson"'. See details. |
sampling |
numeric between 0 and 1. 'sampling' determines the proportion of data to use for initialization. By default, NA (meaning that it uses all data without sampling). |
resolution |
resolution of raster (distance map) (in km) |
ndim |
the number of dimensions of grid cells (ndim^2). Users need to set either resolution or ndim. |
ngroups |
('method = "abramson"' only) the number of groups into which the point-specific bandwidths are partitioned, passed on to 'spatstat.univar::densityAdaptiveKernel()'. By default, 'NULL', which uses ‘spatstat'’s default (the square root of the number of points). Smaller values speed up the computation at the cost of coarser bandwidth approximation. |
To smooth ppp objects, users can choose either the Gaussian mixture model ('method = "mclust"') or Abramson's adaptive smoothing ('method = "abramson"'). The Gaussian mixture model is essentially the method that performs model-based clustering of all the observed points. In this package, we employ the EII model (equal volume, round shape (spherical covariance)). This means that we model observed points by several Gaussian densities with the same, round shape. This is why this model is called fixed-bandwidth smoothing. This is a simple model to smooth observed points, yet given that analyzing spatiotemporal data is often computationally demanding, it is often the best place to start (and end). Sometimes this process can also take time, which is why the 'sampling' option is included in this function: with 'sampling', the model is initialized with a random subset of the points, which considerably reduces the computation time for large datasets.
Another, more precise, method for smoothing outcomes is adaptive smoothing ('method = "abramson"'). This method allows users to vary bandwidths based on 'Abramson (1982)'. Essentially, this model assumes that the bandwidth is inversely proportional to the square root of the target densities. Since the bandwidth is adaptive, the estimation is usually more precise than the Gaussian mixture model. However, the caveat is that this method is often extremely computationally demanding.
Abramson's rule requires a pilot estimate of the spatially varying density,
which 'smooth_ppp()' obtains automatically as follows. First, the points of all
time periods are pooled into a single point pattern. Second, a global bandwidth
is selected for this pooled pattern by Scott's rule of thumb
('spatstat.explore::bw.scott()', with separate bandwidths for the two coordinates),
and the pilot density is estimated by fixed-bandwidth Gaussian kernel smoothing
of the pooled pattern with these bandwidths. Third, point-specific bandwidths are
computed with 'spatstat.explore::bw.abram.ppp()' following the inverse-square-root
rule, , where
is the global bandwidth (the mean of the two Scott bandwidths),
is the pilot density, is the geometric mean of the
terms over the observed points (which puts on
the scale of a fixed bandwidth), and the trimming value (5, the 'spatstat' default)
prevents excessively large bandwidths at isolated points (Hall and Marron, 1988).
Finally, the point-specific bandwidths are assigned back to the points of each
time period, and each time period is smoothed by
'spatstat.univar::densityAdaptiveKernel()' with these bandwidths.
Parallel computation: 'smooth_ppp()' smooths the point patterns of all time periods using the 'future' framework (via 'furrr'), which runs sequentially unless a parallel backend is registered. To smooth the time periods in parallel, set a parallel plan before calling this function, e.g., 'future::plan(future::multisession)'. The results are identical regardless of the plan. Parallelization is most beneficial for 'method = "abramson"', whose computation time is dominated by the adaptive smoothing of each time period; for 'method = "mclust"', the model fitting itself is not parallelized, and the one-time cost of launching the parallel workers may outweigh the gains for the (fast) smoothing stage.
im objects as a list
Abramson, I. S. (1982). On bandwidth variation in kernel estimates — a square root law. The Annals of Statistics, 10(4), 1217–1223.
Hall, P. and Marron, J. S. (1988). Variable window width kernel density estimates of probability densities. Probability Theory and Related Fields, 80, 37–49.
Scott, D. W. (1992). Multivariate Density Estimation: Theory, Practice and Visualization. New York: Wiley.
Other data preparation functions:
get_em_vec(),
get_hfr(),
get_hist(),
imls_to_arr(),
pixel_count_ppp()
# Insurgency outcomes in Iraq, 2006 (first 60 days) dat <- insurgencies_2006 dat$time <- as.numeric(dat$date - min(dat$date) + 1) dat <- dat[dat$time <= 60, ] hfr <- get_hfr(data = dat, col = "type", window = iraq_window, time_col = "time", time_range = c(1, 60), coordinates = c("longitude", "latitude"), combine = TRUE) # Adaptive smoothing of the outcomes # (to run in parallel, call future::plan(future::multisession) first) smoothed <- smooth_ppp(hfr$all_combined, method = "abramson", ndim = 64)# Insurgency outcomes in Iraq, 2006 (first 60 days) dat <- insurgencies_2006 dat$time <- as.numeric(dat$date - min(dat$date) + 1) dat <- dat[dat$time <= 60, ] hfr <- get_hfr(data = dat, col = "type", window = iraq_window, time_col = "time", time_range = c(1, 60), coordinates = c("longitude", "latitude"), combine = TRUE) # Adaptive smoothing of the outcomes # (to run in parallel, call future::plan(future::multisession) first) smoothed <- smooth_ppp(hfr$all_combined, method = "abramson", ndim = 64)
Summary method for objects of class 'cate', returned by [get_cate()]. Summarizes the estimated regression coefficients, the CATE evaluated at the chosen values (both with 90 test of whether at least one non-intercept coefficient differs from zero.
## S3 method for class 'cate' summary(object, ..., significance_level = 0.05)## S3 method for class 'cate' summary(object, ..., significance_level = 0.05)
object |
an object of class 'cate', typically the output of [get_cate()]. |
... |
additional arguments. Currently ignored. |
significance_level |
Numeric scalar between 0 and 1, inclusive, representing the significance level for the chi-square test. The test is used to determine whether at least one of the coefficients (except the intercept) is not equal to 0. Default is 0.05 |
Currently, observed densities (class: obs), estimates (class: est) and heterogeneity estimates (class: cate) are supported by this function.
A named list with three elements: 'result_betas', a data frame of the estimated regression coefficients with 90 'result_values', a data frame of the CATE evaluated at the chosen values with 90 chi-square statistic, its p-value, the significance level, and the test decision.
[get_cate()]
Summary method for objects of class 'est', returned by [get_est()]. Summarizes the estimated causal effects per time period (with 90 confidence intervals) together with the associated windows.
## S3 method for class 'est' summary(object, ...)## S3 method for class 'est' summary(object, ...)
object |
an object of class 'est', typically the output of [get_est()]. |
... |
additional arguments. Currently ignored. |
Currently, observed densities (class: obs) and estimates (class: est) are supported by this function.
A named list with two elements: 'result', a data frame of the point estimates and 90 of windows used in estimation.
[get_est()]
Summary method for objects of class 'obs', returned by [get_obs_dens()]. Prints a short summary of the fitted observed-density model (dispersion parameter, deviance, and null deviance) and returns the estimated model coefficients.
## S3 method for class 'obs' summary(object, ...)## S3 method for class 'obs' summary(object, ...)
object |
an object of class 'obs', typically the output of [get_obs_dens()]. |
... |
additional arguments. Currently ignored. |
Currently, observed densities (class: obs) and estimates (class: est) are supported by this function.
The estimated model coefficients ('object$coef'), returned alongside the printed model summary.
[get_obs_dens()]
Summarize a learned unit-level policy
## S3 method for class 'policy_fit' summary(object, ...)## S3 method for class 'policy_fit' summary(object, ...)
object |
an object returned by [get_policy()]. |
... |
additional arguments. Currently ignored. |
A list containing learned coefficients, fitted-horizon results, order-test details, expected-treatment summaries, and policy-probability summaries.
[get_policy()]
Summarize a unit-level policy value
## S3 method for class 'policy_value' summary(object, ...)## S3 method for class 'policy_value' summary(object, ...)
object |
an object returned by [get_policy_value()]. |
... |
additional arguments. Currently ignored. |
A list containing estimates, uncertainty, stabilization diagnostics, and policy-probability summaries.
[get_policy_value()]
Summarize a unit-level propensity-score model
## S3 method for class 'unit_ps' summary(object, ...)## S3 method for class 'unit_ps' summary(object, ...)
object |
an object returned by [get_unit_ps()]. |
... |
additional arguments. Currently ignored. |
A list containing the model coefficients, probability summary, and balance table.
[get_unit_ps()]