I want to run mantelhaen.test in R which requires 2x2 contingency tables in 3D array form. These tables can be constructed by looping over each row of the dataframe, but I am trying to figure out if there is a vectorised way to do it - ie using apply(df[,c("col1","col2",etc), margin=1, array(x, c(2,2,11))) to make a 3D array for each row of the table (which would then be wrapped in mantelhaen.test).
I have previously got this to work using matrix() for fisher.test in R and Pandas, but in this case I am running into an issue where array() doesn't seem to have any effect on the data. Here is a reproducible example:
df = data.frame(group1_variant_cases = c(2,1,3,0,0,2), group1_nonvariant_cases = c(100,92,33,40,21,87),
group1_variant_controls = c(1,2,1,0,2,1), group1_nonvariant_controls = c(45,61,70,71,31,55),
group2_variant_cases = c(0,2,1,0,1,0), group2_nonvariant_cases = c(201,99,213,52,178,98),
group2_variant_controls = c(1,0,0,0,1,2), group2_nonvariant_controls = c(67,43,12,88,91,73))
apply(head(df,1), 1, function(x) array(x, c(2,2,2)))
Output:
1
[1,] 2
[2,] 100
[3,] 1
[4,] 45
[5,] 0
[6,] 201
[7,] 1
[8,] 67
Any help appreciated!
CodePudding user response:
With apply
, there is simplify
argument which is by default TRUE
. Change it to FALSE
and it works i.e. according to ?apply
If each call to FUN returns a vector of length n, and simplify is TRUE, then apply returns an array of dimension c(n, dim(X)[MARGIN]) if n > 1. If n equals 1, apply returns a vector if MARGIN has length 1 and an array of dimension dim(X)[MARGIN] otherwise.
apply(head(df,3), 1, function(x) array(x, c(2,2,2)), simplify = FALSE)
-output
$`1`
, , 1
[,1] [,2]
[1,] 2 1
[2,] 100 45
, , 2
[,1] [,2]
[1,] 0 1
[2,] 201 67
$`2`
, , 1
[,1] [,2]
[1,] 1 2
[2,] 92 61
, , 2
[,1] [,2]
[1,] 2 0
[2,] 99 43
$`3`
, , 1
[,1] [,2]
[1,] 3 1
[2,] 33 70
, , 2
[,1] [,2]
[1,] 1 0
[2,] 213 12