Skip to contents

grass_report() is the headline entry point for the v0.2.0 Target-2 framework. It takes an N x k binary rating matrix and returns a four-field Report Card: the sample summary (k, N, pi_hat), the primary coefficient and its surface position, the cross-coefficient asymmetry diagnostic delta_hat and flag, and (when flag == "divergent") the per-rater latent-class fit. The full panel of coefficients, surface percentiles, band probabilities, and reference-surface artifacts ride along on the same object for summary(), as.data.frame(), and plot() access.

Usage

grass_report(
  ratings,
  axis = c("inter", "intra"),
  metric = "auto",
  occasion = NULL,
  bands = c(0.5, 0.625, 0.75, 0.875, 1),
  band_labels = c("Poor", "Moderate", "Strong", "Excellent"),
  delta_thresholds = NULL,
  bootstrap_B = 1000L,
  bootstrap_delta_B = 0L,
  verbose = FALSE,
  ...
)

Arguments

ratings

User input: an N x k binary matrix, an N x k data.frame whose columns are 0/1 / logical / 2-level factor, or a list of two equal-length 0/1 vectors (k = 2 paired form). See ?normalize_ratings for accepted shapes.

axis

One of "inter" (default) or "intra". Selects the surface family. The intra-axis path uses occasion to identify viewings.

metric

One of "auto" (default; calls pick_primary_coefficient() per Table 2), "pabak", "ac1", "fleiss_kappa", "icc". Selects which coefficient is the headline in the printed Report Card; the full panel is always populated. (Krippendorff's alpha left the Report Card panel at v0.6.0; it coincides with Fleiss' kappa in the binary fully-crossed case. Use obs_krippendorff_alpha() or position_on_surface() to compute it manually.)

occasion

Reserved for axis = "intra"; ignored when axis = "inter".

bands

Numeric length-5 partition on q in [0.5, 1]. Default c(0.5, 0.625, 0.75, 0.875, 1.0).

band_labels

Character length-4 labels for the bands. Default c("Poor", "Moderate", "Strong", "Excellent").

delta_thresholds

Length-2 numeric vector c(caution, divergent) in percentile points. Default c(9.25, 11.75) (paper Sec.3.2, NP-motivated size-alpha).

bootstrap_B

Integer; bootstrap replicates for the divergent-branch latent-class CIs. Default 1000L. Set lower for fast tests.

bootstrap_delta_B

Integer; subject-resampling replicates for the optional bootstrap distribution of delta_hat. Default 0L (off); values below 50L are treated as off.

verbose

Logical; emit progress messages on long calls. Default FALSE.

...

Reserved for future extension.

Value

An object of class c("grass_card", "list") with fields sample, coefficient, delta, panel, per_rater, surface, call, grass_version, timestamp, inputs, notes. See the v0.2.0 paper-alignment design doc Sec.3.1 for the full structure.

Percentile units. card$coefficient$surface_percentile and card$panel$surface_percentile are reported on the 0-100 scale (e.g., 46.3 means the 46th percentile). The underlying position_on_surface() returns percentile on the 0-1 fraction scale; grass_report() multiplies by 100 to match the paper's prose convention. The print and format methods use ordinal notation ("46th percentile").

Details

The body, in order:

  1. Normalize ratings to a canonical N x k integer matrix Y and derive pi_hat = mean(Y), k = ncol(Y), N = nrow(Y). Validate k >= 2; warn at N < 10; note at N < 30.

  2. Compute the panel of observed coefficients (compute_panel(), internal): at k = 2, PABAK / AC1 / Cohen's kappa; at k >= 3, PABAK / AC1 / Fleiss kappa / ICC.

  3. For each panel coefficient, position the observed value on its DGP-calibrated reference surface via position_on_surface().

  4. Pick the primary coefficient via Table 2 (metric = "auto") or accept the user's override.

  5. Compute the cross-coefficient percentile spread delta_hat (in pp) via check_asymmetry() and tier into aligned / caution / divergent.

  6. If flag == "divergent": run a latent_class_fit() (Dawid-Skene EM at k >= 3; Hui-Walter bounds at k = 2) and attach the per-rater (Se_j, Sp_j) table.

  7. Assemble the grass_card S3 object.

Examples

set.seed(1)
Y <- matrix(rbinom(1000, 1, 0.3), nrow = 200, ncol = 5)
card <- grass_report(ratings = Y)
card                       # print
#> GRASS Report Card
#> 
#>   sample      = 5 raters, N = 200, pi_hat = 0.30
#>   PABAK        = 0.16  ->  48th percentile  (decisive)  <- primary
#>   AC1          = 0.27  ->  46th percentile
#>   Fleiss kappa = 0.00  ->  49th percentile
#>   ICC          = 0.00  ->   0th percentile  [distribution-sensitive]
#>   delta       = 3.1 pp (aligned)
#>   thresholds  = (9.25, 10.75) [calibrated at this (k, N)]
#> 
#>   Notes:
#>     - Fitted-ICC F_key picked via glmer: mu_hat=-0.831, tau2_hat=0.011 -> F_key tau2=0.0625, mu=-0.847.
#>     - Fitted-ICC reference (GLMM-gap corrected) at F_key=LN_mu=-0.847_tau2=0.0625, k=5, N=200 (family=logit_normal, M1=0.303).
#>     - obs_value 0.0034 below achievable minimum (0.0834); q_hat clamped.
#>     - Delta-method SE undefined: dE/dq near zero at q_hat.
#> 
#>   See `summary(...)` for full panel and CI details.
#>   See `plot(...)` for a surface-position visualization.
summary(card)              # full panel + per-rater
#> GRASS Report Card -- summary
#> 
#>   sample       : k = 5 raters, N = 200, pi_hat = 0.304, axis = inter
#>   tau2_hat     : 0.001
#> 
#>   primary coefficient
#>     name         : pabak
#>     observed     : 0.156
#>     percentile   : 47.53 pp
#>     band         : Moderate
#>     qualifier    : decisive
#> 
#>   delta (cross-coefficient asymmetry)
#>     delta_hat    : 3.09 pp
#>     flag         : aligned
#>     thresholds   : caution = 9.25, divergent = 10.75
#> 
#>   panel (full table)
#>     pabak           observed = 0.156  pct = 47.53 pp  band = Moderate     qualifier = decisive
#>     mean_ac1        observed = 0.268  pct = 46.19 pp  band = Moderate     qualifier = decisive
#>     fleiss_kappa    observed = 0.003  pct = 49.27 pp  band = Moderate     qualifier = decisive
#>     icc             observed = 0.003  pct =  0.00 pp  band = Poor         qualifier = decisive
#> 
#>   notes
#>     - Fitted-ICC F_key picked via glmer: mu_hat=-0.831, tau2_hat=0.011 -> F_key tau2=0.0625, mu=-0.847.
#>     - Fitted-ICC reference (GLMM-gap corrected) at F_key=LN_mu=-0.847_tau2=0.0625, k=5, N=200 (family=logit_normal, M1=0.303).
#>     - obs_value 0.0034 below achievable minimum (0.0834); q_hat clamped.
#>     - Delta-method SE undefined: dE/dq near zero at q_hat.
#> 
#>   grass version : 0.6.1
#>   timestamp     : 2026-07-03 13:30:09
as.data.frame(card)        # tidy long-format
#>    coefficient observed_value surface_percentile     band qualifier
#> 1        pabak    0.156000000       47.526453718 Moderate  decisive
#> 2     mean_ac1    0.268413610       46.185613637 Moderate  decisive
#> 3 fleiss_kappa    0.002760133       49.271388205 Moderate  decisive
#> 4          icc    0.003421853        0.001992704     Poor  decisive
#>   band_probability_modal     q_hat   se_q_hat clamped reference_used
#> 1                      1 0.6974835 0.02439619   FALSE    closed-form
#> 2                      1 0.6974805 0.02439621   FALSE    closed-form
#> 3                      1 0.6974835 0.02439619   FALSE    closed-form
#> 4                      1 0.5000000         NA    TRUE     fitted-icc
#>   in_delta_hat is_primary
#> 1         TRUE       TRUE
#> 2         TRUE      FALSE
#> 3         TRUE      FALSE
#> 4        FALSE      FALSE