
Normalize Input to a Contingency or Agreement Table
Source:R/normalizeToConfusion.R
normalizeToConfusion.RdConverts diverse input formats into a numeric contingency matrix suitable for agreement measures (e.g. Cohen's Kappa) or association measures (e.g. Cramer's V). Accepted input formats include tables, matrices, data frames, lists, and raw rating vectors.
Arguments
- x
input object. Accepted formats: a
table()representing a pre-computed contingency table; a square numericmatrixrepresenting a pre-computed contingency table; a numericmatrixwith exactly 2 columns (one per rater); alistordata.framewith exactly 2 elements; or a vector ifyis also supplied.- y
optional second rating vector. If supplied,
xandyare tabulated together.- levels
optional category levels. These rename the categories in place - the counts are not moved - so supplying an order different from the one a table already carries reassigns the counts to other labels. For
mode = "agreement", use an atomic vector of common levels shared by both raters; formode = "association", use a list of length 2,list(x_levels, y_levels).- useNA
passed to
table(). Controls whetherNAvalues appear as a level. One of"no"(default),"ifany", or"always".- mode
character string, either
"agreement"(default) or"association". Agreement mode enforces a square table with identical row and column names. Association mode allows rectangular tables with independent row and column levels.
Value
a numeric contingency matrix with dimnames set according to
levels, if supplied, or derived from the input
Details
The function handles the following input formats:
tableA pre-computed 2D contingency table which is validated via
isConfusionTable(). Formode = "agreement", the table must be square with identical row and column names.matrixEither a pre-computed contingency matrix (square, passing
isConfusionTable()validation) or a two-rater matrix with exactly 2 columns. A 2-column non-square matrix is always treated as a rater matrix; each column is one rater's ratings.- two vectors
If both
xandyare supplied, they are tabulated viatable()after coercing to factors.listordata.framewith 2 elementsEach element is treated as one rater's ratings.
For mode = "agreement", levels must be shared between both raters
and the resulting table is square. For mode = "association", row and
column levels may differ and the table may be rectangular.
See also
isConfusionTable(), raterFrame(), pairApply()
Other agreement:
blandAltmanData(),
raterFrame()
Examples
A <- c("pos","neg","pos","inc")
B <- c("pos","pos","neg","inc")
normalizeToConfusion(A, B)
#> b
#> a inc neg pos
#> inc 1 0 0
#> neg 0 0 1
#> pos 0 1 1
tab <- table(A, B)
normalizeToConfusion(tab)
#> B
#> A inc neg pos
#> inc 1 0 0
#> neg 0 0 1
#> pos 0 1 1
set.seed(1)
C <- sample(c("pos","neg","inc"), length(A), TRUE)
df <- data.frame(R1=A, R2=B, R3=C)
normalizeToConfusion(df[, 1:2]) # R1 vs R2
#> b
#> a inc neg pos
#> inc 1 0 0
#> neg 0 0 1
#> pos 0 1 1
normalizeToConfusion(df[, c(1,3)]) # R1 vs R3
#> b
#> a inc neg pos
#> inc 0 1 0
#> neg 1 0 0
#> pos 0 0 2
# list of rating vectors:
normalizeToConfusion(list(A, B))
#> b
#> a inc neg pos
#> inc 1 0 0
#> neg 0 0 1
#> pos 0 1 1
# use NAs
B[2] <- NA
normalizeToConfusion(A, B, useNA = "always")
#> b
#> a inc neg pos <NA>
#> inc 1 0 0 0
#> neg 0 0 0 1
#> pos 0 1 1 0
#> <NA> 0 0 0 0
anxiety <- data.frame(
rater1 = c(3,3,3,4,5,5,2),
rater2 = c(3,6,4,6,2,4,2),
rater3 = c(2,1,4,4,3,2,1)
)
x <- anxiety[, 1]
y <- anxiety[, 2]
# two vectors:
normalizeToConfusion(x, y)
#> b
#> a 2 3 4 5 6
#> 2 1 0 0 0 0
#> 3 0 1 1 0 1
#> 4 0 0 0 0 1
#> 5 1 0 1 0 0
#> 6 0 0 0 0 0
# matrix / data.frame with 2 columns (subjects x raters):
normalizeToConfusion(cbind(x, y))
#> b
#> a 2 3 4 5 6
#> 2 1 0 0 0 0
#> 3 0 1 1 0 1
#> 4 0 0 0 0 1
#> 5 1 0 1 0 0
#> 6 0 0 0 0 0
normalizeToConfusion(data.frame(x, y))
#> b
#> a 2 3 4 5 6
#> 2 1 0 0 0 0
#> 3 0 1 1 0 1
#> 4 0 0 0 0 1
#> 5 1 0 1 0 0
#> 6 0 0 0 0 0
# list with 2 elements:
normalizeToConfusion(list(x, y))
#> b
#> a 2 3 4 5 6
#> 2 1 0 0 0 0
#> 3 0 1 1 0 1
#> 4 0 0 0 0 1
#> 5 1 0 1 0 0
#> 6 0 0 0 0 0
# pre-built table:
ratingscale <- sort(unique(c(x, y)))
normalizeToConfusion(table(factor(x, levels = ratingscale),
factor(y, levels = ratingscale)))
#>
#> 2 3 4 5 6
#> 2 1 0 0 0 0
#> 3 0 1 1 0 1
#> 4 0 0 0 0 1
#> 5 1 0 1 0 0
#> 6 0 0 0 0 0
d.anxiety <- data.frame(
rater = c("rater1", "rater1", "rater1", "rater1", "rater1", "rater1", "rater1",
"rater2", "rater2", "rater2", "rater2", "rater2", "rater2", "rater2",
"rater3", "rater3", "rater3", "rater3", "rater3", "rater3", "rater3"),
rating = c(3, 3, 3, 4, 5, 5, 2,
3, 6, 4, 6, 2, 4, 2,
2, 1, 4, 4, 3, 2, 1),
subj = c(1, 2, 3, 4, 5, 6, 7,
1, 2, 3, 4, 5, 6, 7,
1, 2, 3, 4, 5, 6, 7)
)
# via raterFrame (wide format, subjects x raters):
normalizeToConfusion(
raterFrame(rating ~ subj | rater, data = d.anxiety,
subset = rater %in% c("rater1", "rater2"), dropSubj = TRUE)
)
#> b
#> a 2 3 4 5 6
#> 2 1 0 0 0 0
#> 3 0 1 1 0 1
#> 4 0 0 0 0 1
#> 5 1 0 1 0 0
#> 6 0 0 0 0 0