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.

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. Since R version 3.5.0, this also increases the internal stack size which allows larger problems to be solved, however sometimes needing hours. In such cases, simulate.p.values=TRUE may 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.

detailed

logical value. Default is FALSE. If TRUE, a detailed result is shown.

...

Other arguments passed to the function fisher_test().

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 function fisher.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              alter…¹ p.sig…²
#> * <dbl>    <dbl>    <dbl>    <dbl>     <dbl> <chr>               <chr>   <chr>
#> 1  1000     12.2 8.77e-22     6.27      26.6 Fisher's Exact test two.si… ****
#> # … with abbreviated variable names ¹​alternative, ²​p.signif

# 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.1e-15 Fisher's Exact test two.sided   ****

# Pairwise comparison between groups
pairwise_fisher_test(xtab)
#> # A tibble: 6 × 6
#> * <chr>  <chr>  <dbl>    <dbl>    <dbl> <chr>
#> 1 grp1   grp2     219 2.39e-11 1.2 e-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.51e- 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
#> * <chr>  <chr>  <dbl>    <dbl>    <dbl> <chr>
#> 1 1st    2nd      610 2.78e- 7 8.34e- 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
#> * <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.783 ns