
Compute interaction table between a facet and a grouping variable
Source:R/api-advanced.R, R/api-plotting-dispatch.R
dif_interaction_table.RdProduces a cell-level interaction table showing Obs-Exp differences, scaled residuals, and absolute residual mean comparisons for each facet-level x group-value cell.
Usage
dif_interaction_table(
fit,
diagnostics,
facet,
group,
data = NULL,
min_obs = 10,
p_adjust = "holm",
abs_t_warn = 2,
abs_bias_warn = 0.5
)
# S3 method for class 'mfrm_dif_interaction'
plot(x, type = "heatmap", ...)Arguments
- fit
Output from
fit_mfrm().- diagnostics
Output from
diagnose_mfrm().- facet
Character scalar naming the facet.
- group
Character scalar naming the grouping column.
- data
Optional data frame with the group column. If
NULL(default), the data stored infit$prep$datais used, but it must contain thegroupcolumn. All fitted response columns, including the weight column if used, are required. Subsets and repeated responses followanalyze_dff()'s response-matching contract; unmatched rows remain visible in$cases.- min_obs
Minimum observations per cell. Cells with fewer than this many observations are marked sparse; scaled residuals and magnitude flags are
NA. Observed and expected score summaries remain available.- p_adjust
Retained for compatibility; unused because no p-values are reported. Default
"holm".- abs_t_warn
Retained for compatibility; unused because scaled residuals are not t statistics.
flag_tisNA.- abs_bias_warn
Threshold for marking the absolute observed-minus-expected average, in score units. Default
0.5. This is a descriptive magnitude rule.- x
A result from
dif_interaction_table().- type
The sole view,
"heatmap".- ...
Heatmap controls below, plus
draw = FALSEto return data without drawing. This input acceptsmetric = "obs_exp"or"t";"contrast"requires a result fromanalyze_dff().
Value
Object of class mfrm_dif_interaction with:
table: tibble with per-cell statistics and flags.cases: requested-row matching and exclusion audit.summary: tibble summarizing flagged and sparse cell counts.gpcm_boundary: forGPCMfits, a capability-boundary table.config: list of analysis parameters.
For plot(): Invisibly, a ggplot object carrying matrix, pairs, the
selected metric and retained interpretation notes. Use
plot_data(p, "matrix") to extract the matrix from a saved plot p.
Details
This function uses observation-level residuals computed from the fitted model rather than re-estimating it. For each facet-level x group-value cell, it computes:
N: number of observations in the cell
NPersons: number of distinct Persons in the cell, not an independence certificate
ObsScore: sum of observed scores
ExpScore: sum of expected scores
ObsExpAvg: mean observed-minus-expected difference
Var_sum: sum of model variances
StdResidual: (ObsScore - ExpScore) / sqrt(Var_sum)
t, df, p_value, p_adjusted, flag_t:
NA, retained for compatibility
plot() method: Plot a differential-functioning interaction grid
Display saved residual means by facet level and group. This is a descriptive screen for follow-up; residual differences do not isolate differential functioning.
When to use this instead of analyze_dff()
Use dif_interaction_table() when you want cell-level screening for a
single facet-by-group table. Use analyze_dff() when you want group-pair
comparisons. Neither residual output tests differential functioning.
Further guidance
For plot selection and follow-up diagnostics, see mfrmr_visual_diagnostics.
Interpreting output
$table: the full interaction table with one row per cell.$cases: requested-row matching and exclusion audit, also kept bysummary().$summary: overview counts of flagged and sparse cells.$config: analysis configuration parameters.$gpcm_boundary: forGPCMfits, a capability-boundary table marking the table as caveated DFF screening evidence.flag_biasrecords|ObsExpAvg| > abs_bias_warnin score units. It does not establish differential functioning.flag_tis unavailable.Sparse cells (N < min_obs) have
sparse = TRUEand unavailable scaled residuals and magnitude flags. The score means and counts are retained.
GPCM boundary
For GPCM, the interaction table uses the fitted slope-aware
expected-score/residual scale and should be reported as screening evidence,
not as a standalone fairness, invariance, or operational subgroup decision.
Residual means can differ even when response parameters are the same between groups. These summaries provide no p-values or t-based decisions. Recompute older saved tables with this function using the fitted model; no refit is needed.
Typical workflow
Fit a model with
fit_mfrm().Run
dif_interaction_table(fit, diag, facet = "Rater", group = "Gender", data = df).Inspect
$tablefor flagged cells.Visualize with plot(x, type = "heatmap").
Interpretation
For plot():
Positive "obs_exp" values mean observed scores exceed model expectations;
negative values mean they fall below expectations. These values are in
score units, not logits. The "t" metric is a scaled residual without a
calibrated test or p-value. Color and optional threshold outlines are
descriptive; an unavailable cell is not a zero residual.
Heatmap appearance
show_values = TRUElabels cells;value_digits = 2controls rounding.flag_threshold = NULLadds no flags. A non-negative value outlines cells at or above that absolute value;flag_color = "black"sets the border.scale_limit = NULLuses the observed range. A positive value fixes symmetric color limits for comparing plots. It does not change saved values.
See also
analyze_dff(), plot(x, type = "heatmap"), dif_report(),
estimate_bias()
dif_interaction_table(), plot.mfrm_dif(), mfrmr_plot_migration
Examples
# Supplementary workflow: run explicitly to keep routine checks brief.
# example("dif_interaction_table", run.dontrun = TRUE)
if (FALSE) { # \dontrun{
toy <- load_mfrmr_data("example_bias")
fit <- fit_mfrm(toy, "Person", c("Rater", "Criterion"), "Score",
method = "JML", model = "RSM", maxit = 300)
diag <- diagnose_mfrm(fit, residual_pca = "none")
int <- dif_interaction_table(fit, diag, facet = "Rater",
group = "Group", data = toy, min_obs = 2)
int$summary
head(int$table[, c("Level", "GroupValue", "ObsExpAvg", "flag_bias")])
} # }
# Supplementary workflow: run explicitly to keep routine checks brief.
# example("plot.mfrm_dif_interaction", run.dontrun = TRUE)
if (FALSE) { # \dontrun{
ratings <- load_mfrmr_data("example_bias")
fit <- fit_mfrm(ratings, "Person", c("Rater", "Criterion"), "Score",
method = "JML", model = "RSM", maxit = 300)
diag <- diagnose_mfrm(fit, residual_pca = "none")
int <- dif_interaction_table(fit, diag, facet = "Rater",
group = "Group", data = ratings, min_obs = 2)
heat <- plot(int, type = "heatmap", metric = "obs_exp", draw = FALSE)
dim(plot_data(heat, "matrix"))
# Obs-Exp is in score units, not logits. A scaled residual
# (metric = "t") is descriptive, not a calibrated t-test.
} # }