Create a contingency table (optionally a sparse matrix) from crossclassifying factors, usually contained in a data frame, using a formula interface.
1 2 3 4 5 6 
formula 
a formula object with the crossclassifying variables
(separated by 
data 
an optional matrix or data frame (or similar: see

subset 
an optional vector specifying a subset of observations to be used. 
sparse 
logical specifying if the result should be a
sparse matrix, i.e., inheriting from

na.action 
a function which indicates what should happen when
the data contain 
addNA 
logical indicating if 
exclude 
a vector of values to be excluded when forming the set of levels of the classifying factors. 
drop.unused.levels 
a logical indicating whether to drop unused
levels in the classifying factors. If this is 
x 
an object of class 
na.print 
character string (or 
... 
further arguments passed to or from other methods. 
There is a summary
method for contingency table objects created
by table
or xtabs(*, sparse = FALSE)
, which gives basic
information and performs a chisquared test for independence of
factors (note that the function chisq.test
currently
only handles 2d tables).
If a left hand side is given in formula
, its entries are simply
summed over the cells corresponding to the right hand side; this also
works if the lhs does not give counts.
For variables in formula
which are factors, exclude
must be specified explicitly; the default exclusions will not be used.
In R versions before 3.4.0, e.g., when na.action = na.pass
,
sometimes zeroes (0
) were returned instead of NA
s.
By default, when sparse = FALSE
,
a contingency table in array representation of S3 class c("xtabs",
"table")
, with a "call"
attribute storing the matched call.
When sparse = TRUE
, a sparse numeric matrix, specifically an
object of S4 class
dgTMatrix
from package
Matrix.
table
for traditional crosstabulation, and
as.data.frame.table
which is the inverse operation of
xtabs
(see the DF
example below).
sparseMatrix
on sparse
matrices in package Matrix.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47  ## 'esoph' has the frequencies of cases and controls for all levels of
## the variables 'agegp', 'alcgp', and 'tobgp'.
xtabs(cbind(ncases, ncontrols) ~ ., data = esoph)
## Output is not really helpful ... flat tables are better:
ftable(xtabs(cbind(ncases, ncontrols) ~ ., data = esoph))
## In particular if we have fewer factors ...
ftable(xtabs(cbind(ncases, ncontrols) ~ agegp, data = esoph))
## This is already a contingency table in array form.
DF < as.data.frame(UCBAdmissions)
## Now 'DF' is a data frame with a grid of the factors and the counts
## in variable 'Freq'.
DF
## Nice for taking margins ...
xtabs(Freq ~ Gender + Admit, DF)
## And for testing independence ...
summary(xtabs(Freq ~ ., DF))
## with NA's
DN < DF; DN[cbind(6:9, c(1:2,4,1))] < NA; DN
tools::assertError(# 'na.fail' should fail :
xtabs(Freq ~ Gender + Admit, DN, na.action=na.fail))
xtabs(Freq ~ Gender + Admit, DN)
xtabs(Freq ~ Gender + Admit, DN, na.action = na.pass)
## The Female:Rejected combination has NA 'Freq' (and NA prints 'invisibly' as "")
xtabs(Freq ~ Gender + Admit, DN, addNA = TRUE) # ==> count NAs
## Create a nice display for the warp break data.
warpbreaks$replicate < rep_len(1:9, 54)
ftable(xtabs(breaks ~ wool + tension + replicate, data = warpbreaks))
###  Sparse Examples 
if(require("Matrix")) {
## similar to "nlme"s 'ergoStool' :
d.ergo < data.frame(Type = paste0("T", rep(1:4, 9*4)),
Subj = gl(9, 4, 36*4))
print(xtabs(~ Type + Subj, data = d.ergo)) # 4 replicates each
set.seed(15) # a subset of cases:
print(xtabs(~ Type + Subj, data = d.ergo[sample(36, 10), ], sparse = TRUE))
## Hypothetical twolevel setup:
inner < factor(sample(letters[1:25], 100, replace = TRUE))
inout < factor(sample(LETTERS[1:5], 25, replace = TRUE))
fr < data.frame(inner = inner, outer = inout[as.integer(inner)])
print(xtabs(~ inner + outer, fr, sparse = TRUE))
}

Questions? Problems? Suggestions? Tweet to @rdrrHQ or email at ian@mutexlabs.com.
Please suggest features or report bugs with the GitHub issue tracker.
All documentation is copyright its authors; we didn't write any of that.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.