rmatrixpercentagecrosstab

How to calculate percentages for rows and columns in a cross-tab?


I have a 3 level contingency table for which I'm trying to calculate the percentages for each cell of the table as a function of the sum row total for each row and then a function of the sum column total for each column. Here is the data which I want to calculate the percentages for:

"A2"
                 0_15m 15_30m 30_>40m

<35yrs  0_4cm      217     30       3
        20_80cm    282     42      14
        4_20cm     315    182      82
>=35yrs 0_4cm      334     63       3
        20_80cm    310     75      23
        4_20cm     433    110      95

dput(A2)

structure(c(217L, 282L, 315L, 334L, 310L, 433L, 30L, 42L, 182L, 
63L, 75L, 110L, 3L, 14L, 82L, 3L, 23L, 95L), .Dim = c(6L, 3L), class = "ftable", row.vars = structure(list(
    c("<35yrs", ">=35yrs"), c("0_4cm", "20_80cm", "4_20cm")), .Names = c("", 
"")), col.vars = structure(list(c("0_15m", "15_30m", "30_>40m"
)), .Names = ""))

I've tried using colPercent function as well as calculating manually (see example):

Where A2 is the ftable of data above:

rpc <- A2 / rowSums(A2) * 100
cpc <- A2 / colSums(A2) * 100


As you can see, the row percentages are calculated correctly (All sum to 100 across the rows), however column percentages are in some cases over 100% and therefore must not have been calculated correctly.


"Row percentages"
                     0_15m    15_30m   30_>40m

<35yrs  0_4cm    86.800000 12.000000  1.200000
        20_80cm  83.431953 12.426036  4.142012
        4_20cm   54.404145 31.433506 14.162349
>=35yrs 0_4cm    83.500000 15.750000  0.750000
        20_80cm  75.980392 18.382353  5.637255
        4_20cm   67.868339 17.241379 14.890282

 "Column Percentages"
                       0_15m      15_30m     30_>40m

<35yrs  0_4cm     11.4754098   1.5864622   0.1586462
        20_80cm   56.1752988   8.3665339   2.7888446
        4_20cm   143.1818182  82.7272727  37.2727273
>=35yrs 0_4cm     17.6626124   3.3315706   0.1586462
        20_80cm   61.7529880  14.9402390   4.5816733
        4_20cm   196.8181818  50.0000000  43.1818182

Solution

  • Division works row-wise and not column wise as needed here. To get colSums to work you can transpose, divide and then transpose again

    t(t(as.matrix(A2))/colSums(A2)) * 100
    
    #                 0_15m 15_30m 30_>40m
    #                                     
    #<35yrs  0_4cm    11.48   5.98    1.36
    #        20_80cm  14.91   8.37    6.36
    #        4_20cm   16.66  36.25   37.27
    #>=35yrs 0_4cm    17.66  12.55    1.36
    #        20_80cm  16.39  14.94   10.45
    #        4_20cm   22.90  21.91   43.18
    

    Or another option is

    A2 / colSums(A2)[col(A2)] * 100