Home > Mobile >  How to use apply() on an array of matrices in R?
How to use apply() on an array of matrices in R?

Time:03-07

I am trying to use apply() on an array of matrices. Here is an example:

data(UCBAdmissions)
fisher.test(UCBAdmissions[,,1]) #This works great
apply(UCBAdmissions, c(1,2,3), fisher.test) #This fails

CodePudding user response:

Something like this: Personally I do it this way: First make a list UCB_list

then bind list elements to dataframe with rbindlist from data.table

finally, use lapply indicating the column y=df$Gender you want to iterate through:

library(data.table)
UCB_list <- list(UCBAdmissions)
df <- rbindlist(lapply(UCB_list, data.frame))

lapply(df, fisher.test, y = df$Gender)
> lapply(df, fisher.test, y = df$Gender)
$Admit

    Fisher's Exact Test for Count Data

data:  X[[i]] and df$Gender
p-value = 1
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
 0.1537975 6.5020580
sample estimates:
odds ratio 
         1 


$Gender

    Fisher's Exact Test for Count Data

data:  X[[i]] and df$Gender
p-value = 7.396e-07
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
 16.56459      Inf
sample estimates:
odds ratio 
       Inf 


$Dept

    Fisher's Exact Test for Count Data

data:  X[[i]] and df$Gender
p-value = 1
alternative hypothesis: two.sided


$Freq

    Fisher's Exact Test for Count Data

data:  X[[i]] and df$Gender
p-value = 0.4783
alternative hypothesis: two.sided

CodePudding user response:

The UCBAdmissions data has six table data within Dept part, namely: "A", "B", "C" , "D", "E" , and "F".

dimnames(UCBAdmissions)
#$Admit
#[1] "Admitted" "Rejected"

#$Gender
#[1] "Male"   "Female"

#$Dept
#[1] "A" "B" "C" "D" "E" "F"

You can apply fisher.test to each of these six tables. It is not clear to me from your code apply(UCBAdmissions, c(1,2,3), fisher.test) to which part of the six tables you want to apply fisher.test.

If you want to apply fisher.test to the first three of the six tables, namely "A", "B", and "C", you need to subset the UCBAdmissions data first, and then set the dimension to 3.

apply(UCBAdmissions[,,1:3], 3, fisher.test)

# $A
# 
# Fisher's Exact Test for Count Data
# 
# data:  array(newX[, i], d.call, dn.call)
# p-value = 1.669e-05
# alternative hypothesis: true odds ratio is not equal to 1
# 95 percent confidence interval:
#  0.1970420 0.5920417
# sample estimates:
# odds ratio 
#  0.3495628 
# 
# 
# $B
# 
#   Fisher's Exact Test for Count Data
# 
# data:  array(newX[, i], d.call, dn.call)
# p-value = 0.6771
# alternative hypothesis: true odds ratio is not equal to 1
# 95 percent confidence interval:
#   0.2944986 2.0040231
# sample estimates:
#   odds ratio 
# 0.8028124 
# 
# 
# $C
# 
# Fisher's Exact Test for Count Data
# 
# data:  array(newX[, i], d.call, dn.call)
# p-value = 0.3866
# alternative hypothesis: true odds ratio is not equal to 1
# 95 percent confidence interval:
#  0.8452173 1.5162918
# sample estimates:
# odds ratio 
#     1.1329 

Another option is to replace 3 with the dimension name:

apply(UCBAdmissions[,,1:3], "Dept", fisher.test)

This will give exactly the same result as the previous code.

In another case, if you want to apply fisher.test to contingency tables between Admit and Dept for "A", "B", "C", grouped by Gender, you can use:

apply(UCBAdmissions[,,1:3], "Gender", fisher.test)

# $Male
# 
# Fisher's Exact Test for Count Data
# 
# data:  array(newX[, i], d.call, dn.call)
# p-value = 7.217e-16
# alternative hypothesis: two.sided
# 
# 
# $Female
# 
#   Fisher's Exact Test for Count Data
# 
# data:  array(newX[, i], d.call, dn.call)
# p-value < 2.2e-16
# alternative hypothesis: two.sided

To show what is being tested more clearly, I reshape the data and then filter it so that I have male only students in depts A, B, and C. Then, I apply fisher.test to the data

DF <- UCBAdmissions %>% as.data.frame %>% filter(Gender == "Male", Dept == "A" | Dept == "B" | Dept == "C") %>% pivot_wider(-Gender, names_from = Admit, values_from = Freq); DF
# # A tibble: 3 x 3
# Dept  Admitted Rejected
# <fct>    <dbl>    <dbl>
#   1 A          512      313
# 2 B          353      207
# 3 C          120      205

fisher.test(DF[1:3, 2:3])
# 
# Fisher's Exact Test for Count Data
# 
# data:  DF[1:3, 2:3]
# p-value = 7.217e-16
# alternative hypothesis: two.sided

The result is exactly the same as the one with apply(UCBAdmissions[,,1:3], "Gender", fisher.test) for Male.

  • Related