Search code examples
rprintinghighlighthighlightingcontingency

How to highlight the max of each column in a contingency table?


I am trying to highlight the maximum value of each column in a contingency table in R.

What I tried so far

tbl <- as.matrix(table(c(iris[5], data.frame(Petal.Width = cut(iris$Petal.Width, 3)))))
pos <- cbind(apply(tbl, 2, which.max), 1:dim(tbl)[2])
tbl <- addmargins(tbl)

# First attempt
tbl2 <- tbl
tbl2[pos] <- -tbl2[pos]
tbl2
##             Petal.Width
## Species      (0.0976,0.9] (0.9,1.7] (1.7,2.5] Sum
##   setosa              -50         0         0  50
##   versicolor            0       -49         1  50
##   virginica             0         5       -45  50
##   Sum                  50        54        46 150

# Second attempt
tbl2 <- tbl
tbl[pos] <- paste("*", tbl[pos])
print(tbl, justify = "right")
##             Petal.Width
## Species      (0.0976,0.9] (0.9,1.7] (1.7,2.5] Sum 
##   setosa     * 50            0         0        50
##   versicolor    0         * 49         1        50
##   virginica     0            5      * 45        50
##   Sum          50           54        46       150

The first attempt would work if I could find a possibility to change the "-" to "* " but keep the numeric data type.

The second attempt would work if I could find a possibility to right align the values (which are now character strings) with the column names.

My question
Can you give me a solution to make at least one of these attempts work - or a completely different solution with which I can highlight the maximum value of each column in a contingency table?

Thank you


Solution

  • The solution is relatively unexpected due to some inconsistencies between different print methods in R:

    tbl2 <- tbl
    tbl[pos] <- paste("*", tbl[pos])
    print(tbl, quote = FALSE, right = TRUE)
    ##             Petal.Width
    ## Species      (0.0976,0.7] (0.7,1.3] (1.3,1.9] (1.9,2.5] Sum
    ##   setosa             * 50         0         0         0  50
    ##   versicolor            0      * 28      * 22         0  50
    ##   virginica             0         0        21      * 29  50
    ##   Sum                  50        28        43        29 150
    

    The documentation on print.matrix says:

    print.matrix and print.default both print matrices, and each has at least an optional argument that the other lacks. Also, both directly dispatch into .Internal code directly instead of relying on each other. This mainly stems from historic compatibility and similar reasons should be changed in the future.