Getting Started with citestR

Overview

citestR is a lightweight R client for the citest Python package. It lets you run the conditional-independence-of-missingness test without using reticulate at runtime — all communication happens over a local HTTP connection to a FastAPI server that wraps the Python package.

1. A small executable example

The chunk below runs during vignette build. It uses mocked HTTP responses, so it exercises the package interface without requiring a live Python backend.

mock_json_response <- function(body, status = 200L) {
  function(req) {
    httr2::response(
      status_code = status,
      headers = list("Content-Type" = "application/json"),
      body = charToRaw(jsonlite::toJSON(body, auto_unbox = TRUE))
    )
  }
}

pkg_env <- citestR:::.pkg_env
old_process <- pkg_env$process
old_port <- pkg_env$port
old_base_url <- pkg_env$base_url
on.exit({
  pkg_env$process <- old_process
  pkg_env$port <- old_port
  pkg_env$base_url <- old_base_url
}, add = TRUE)

pkg_env$process <- list(is_alive = function() TRUE)
pkg_env$port <- 9999L
pkg_env$base_url <- "http://127.0.0.1:9999"

# Mock a ci_test response
mock_fit <- mock_json_response(list(
  model_id = "test-001",
  dataset_id = "ds-001",
  results = list(
    m = 0.12,
    B = 0.04,
    W_bar = 0.01,
    T = 0.05,
    t_k = 2.5,
    p_k = 0.017,
    p_2s = 0.034,
    df = 9
  )
))

example_data <- data.frame(
  Y  = c(1.2, -0.4, 0.7, 0.3, -1.1),
  X1 = c(NA, 0.5, -1.1, 0.8, NA),
  X2 = c(0.3, 1.4, -0.2, 0.6, 0.9)
)

result <- httr2::with_mocked_responses(mock_fit, {
  ci_test(example_data, y = "Y", m = 2L, n_folds = 2L)
})

result
#> 
#>   Conditional Independence of Missingness Test
#> 
#>   Mean diff in BCE: 0.12 
#>   t-statistic:     2.5 
#>   df:              9 
#>   p-value:         0.034 (two-sided)
#> 
#>   Result: Evidence against conditional independence (p < 0.05)

2. Install the Python backend

If you don’t already have a Python environment with citest installed, the package provides a helper:

library(citestR)

# Creates a virtualenv called "citest_env" and installs the citest API backend
install_backend(method = "pip")

You only need to do this once.

3. Run a test

library(citestR)

# Example data frame with some missing values
set.seed(42)
n <- 500
df <- data.frame(
  Y  = rnorm(n),
  X1 = rnorm(n),
  X2 = rnorm(n),
  X3 = rnorm(n)
)
# Introduce MAR missingness on X2
df$X2[df$X1 > 0.5] <- NA

# Run the CI test (server starts automatically)
result <- ci_test(
  data       = df,
  y          = "Y",
  imputer    = "iterative",
  classifier = "rf",
  m          = 5L,
  n_folds    = 5L
)

result$results

The first call starts the Python server in the background; subsequent calls reuse the running process.

4. Retrieve a summary

summary_info <- get_summary(result$model_id)
summary_info

5. Imputer diagnostics

r2 <- imputer_r2(result$model_id, mask_frac = 0.2, m_eval = 1L)
r2$mean_r2
r2$per_variable

6. Sensitivity calibration

# Single kappa value
compute_kappa(r2_x_z = 0.5, beta_yx = 0.3, gamma_x = 0.2)

# Full calibration table
cal <- kappa_calibration_table()
head(cal)

# Pivot for a fixed beta
calibration_pivot(beta_yx = 0.3)

7. Simulated datasets

sim <- simulate_data("single_mar", n = 300, ci = TRUE)
sim$dataset_id
sim$pct_missing

8. Stopping the server

The server shuts down automatically when the R session ends. To stop it manually:

stop_server()

mirror server hosted at Truenetwork, Russian Federation.