Performs Fisher's exact test for testing the null of independence of rows and columns in a contingency table.
Wrappers around the R base function fisher.test() but
have the advantage of performing pairwise and row-wise fisher tests, the
post-hoc tests following a significant chi-square test of homogeneity for 2xc
and rx2 contingency tables.
Usage
fisher_test(
xtab,
workspace = 2e+05,
alternative = "two.sided",
conf.int = TRUE,
conf.level = 0.95,
simulate.p.value = FALSE,
B = 2000,
detailed = FALSE,
...
)
pairwise_fisher_test(xtab, p.adjust.method = "holm", detailed = FALSE, ...)
row_wise_fisher_test(xtab, p.adjust.method = "holm", detailed = FALSE, ...)Arguments
- xtab
a contingency table in a matrix form.
- workspace
an integer specifying the size of the workspace used in the network algorithm. In units of 4 bytes. Only used for non-simulated p-values larger than \(2 \times 2\) tables. This also increases the internal stack size which allows larger problems to be solved, sometimes needing hours. In such cases,
simulate.p.values = TRUEmay be more reasonable.- alternative
indicates the alternative hypothesis and must be one of
"two.sided","greater"or"less". You can specify just the initial letter. Only used in the \(2 \times 2\) case.- conf.int
logical indicating if a confidence interval for the odds ratio in a \(2 \times 2\) table should be computed (and returned).
- conf.level
confidence level for the returned confidence interval. Only used in the \(2 \times 2\) case and if
conf.int = TRUE.- simulate.p.value
a logical indicating whether to compute p-values by Monte Carlo simulation, in larger than \(2 \times 2\) tables.
- B
an integer specifying the number of replicates used in the Monte Carlo test when
simulate.p.valueis true.- detailed
logical value. Default is FALSE. If TRUE, a detailed result is shown.
- ...
Other arguments passed to the function
fisher_test().- p.adjust.method
method to adjust p values for multiple comparisons. Used when pairwise comparisons are performed. Allowed values include "holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none". If you don't want to adjust the p value (not recommended), use p.adjust.method = "none".
Value
return a data frame with some the following columns:
group: the categories in the row-wise proportion tests.p: p-value.p.adj: the adjusted p-value.method: the used statistical test.p.signif, p.adj.signif: the significance level of p-values and adjusted p-values, respectively.estimate: an estimate of the odds ratio. Only present in the 2 by 2 case.alternative: a character string describing the alternative hypothesis.conf.low,conf.high: a confidence interval for the odds ratio. Only present in the 2 by 2 case and if argument conf.int = TRUE.
The returned object has an attribute called args, which is a list holding the test arguments.
Functions
fisher_test(): performs Fisher's exact test for testing the null of independence of rows and columns in a contingency table with fixed marginals. Wrapper around the functionfisher.test().pairwise_fisher_test(): pairwise comparisons between proportions, a post-hoc tests following a significant Fisher's exact test of homogeneity for 2xc design.row_wise_fisher_test(): performs row-wise Fisher's exact test of count data, a post-hoc tests following a significant chi-square test of homogeneity for rx2 contingency table. The test is conducted for each category (row).
Examples
# Comparing two proportions
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# Data: frequencies of smokers between two groups
xtab <- as.table(rbind(c(490, 10), c(400, 100)))
dimnames(xtab) <- list(
group = c("grp1", "grp2"),
smoker = c("yes", "no")
)
xtab
#> smoker
#> group yes no
#> grp1 490 10
#> grp2 400 100
# compare the proportion of smokers
fisher_test(xtab, detailed = TRUE)
#> # A tibble: 1 × 8
#> n estimate p conf.low conf.high method alternative p.signif
#> * <dbl> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <chr>
#> 1 1000 12.2 8.77e-22 6.27 26.6 Fisher's Exac… two.sided ****
# Homogeneity of proportions between groups
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# H0: the proportion of smokers is similar in the four groups
# Ha: this proportion is different in at least one of the populations.
#
# Data preparation
grp.size <- c( 106, 113, 156, 102 )
smokers <- c( 50, 100, 139, 80 )
no.smokers <- grp.size - smokers
xtab <- as.table(rbind(
smokers,
no.smokers
))
dimnames(xtab) <- list(
Smokers = c("Yes", "No"),
Groups = c("grp1", "grp2", "grp3", "grp4")
)
xtab
#> Groups
#> Smokers grp1 grp2 grp3 grp4
#> Yes 50 100 139 80
#> No 56 13 17 22
# Compare the proportions of smokers between groups
fisher_test(xtab, detailed = TRUE)
#> # A tibble: 1 × 5
#> n p method alternative p.signif
#> * <dbl> <dbl> <chr> <chr> <chr>
#> 1 477 6.10e-15 Fisher's Exact test two.sided ****
# Pairwise comparison between groups
pairwise_fisher_test(xtab)
#> # A tibble: 6 × 6
#> group1 group2 n p p.adj p.adj.signif
#> * <chr> <chr> <dbl> <dbl> <dbl> <chr>
#> 1 grp1 grp2 219 2.39e-11 1.19e-10 ****
#> 2 grp1 grp3 262 1.22e-13 7.32e-13 ****
#> 3 grp1 grp4 208 3.79e- 6 1.52e- 5 ****
#> 4 grp2 grp3 269 1 e+ 0 1 e+ 0 ns
#> 5 grp2 grp4 215 6.35e- 2 1.27e- 1 ns
#> 6 grp3 grp4 258 2.17e- 2 6.52e- 2 ns
# Pairwise proportion tests
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# Data: Titanic
xtab <- as.table(rbind(
c(122, 167, 528, 673),
c(203, 118, 178, 212)
))
dimnames(xtab) <- list(
Survived = c("No", "Yes"),
Class = c("1st", "2nd", "3rd", "Crew")
)
xtab
#> Class
#> Survived 1st 2nd 3rd Crew
#> No 122 167 528 673
#> Yes 203 118 178 212
# Compare the proportion of survived between groups
pairwise_fisher_test(xtab)
#> # A tibble: 6 × 6
#> group1 group2 n p p.adj p.adj.signif
#> * <chr> <chr> <dbl> <dbl> <dbl> <chr>
#> 1 1st 2nd 610 2.78e- 7 8.33e- 7 ****
#> 2 1st 3rd 1031 3.68e-30 1.84e-29 ****
#> 3 1st Crew 1210 1.81e-34 1.09e-33 ****
#> 4 2nd 3rd 991 8.19e- 7 1.64e- 6 ****
#> 5 2nd Crew 1170 2.77e- 8 1.11e- 7 ****
#> 6 3rd Crew 1591 5.98e- 1 5.98e- 1 ns
# Row-wise proportion tests
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# Data: Titanic
xtab <- as.table(rbind(
c(180, 145), c(179, 106),
c(510, 196), c(862, 23)
))
dimnames(xtab) <- list(
Class = c("1st", "2nd", "3rd", "Crew"),
Gender = c("Male", "Female")
)
xtab
#> Gender
#> Class Male Female
#> 1st 180 145
#> 2nd 179 106
#> 3rd 510 196
#> Crew 862 23
# Compare the proportion of males and females in each category
row_wise_fisher_test(xtab)
#> # A tibble: 4 × 5
#> group n p p.adj p.adj.signif
#> * <chr> <dbl> <dbl> <dbl> <chr>
#> 1 1st 2201 9.38e-25 2.81e-24 ****
#> 2 2nd 2201 3.96e-11 7.92e-11 ****
#> 3 3rd 2201 8.67e- 7 8.67e- 7 ****
#> 4 Crew 2201 8.02e-85 3.21e-84 ****
# A r x c table Agresti (2002, p. 57) Job Satisfaction
Job <- matrix(c(1,2,1,0, 3,3,6,1, 10,10,14,9, 6,7,12,11), 4, 4,
dimnames = list(income = c("< 15k", "15-25k", "25-40k", "> 40k"),
satisfaction = c("VeryD", "LittleD", "ModerateS", "VeryS")))
fisher_test(Job)
#> # A tibble: 1 × 3
#> n p p.signif
#> * <dbl> <dbl> <chr>
#> 1 96 0.783 ns
fisher_test(Job, simulate.p.value = TRUE, B = 1e5)
#> # A tibble: 1 × 3
#> n p p.signif
#> * <dbl> <dbl> <chr>
#> 1 96 0.781 ns