Converting array to matrix in R

11,165

Solution 1

You can easily get columns of values by flattening the matrix on the 3rd margin:

z1 <- apply(priCPT.i6, 3L, c)
## we can also simply use `matrix`; but remember to set `dimnames`
## otherwise we lose dimnames
## z1 <- matrix(priCPT.i6, ncol = 2L,
##              dimnames = list(NULL, dimnames(priCPT.i6)[[3]]))

What you need for the rest is to append the "dimnames" columns:

z2 <- expand.grid(dimnames(priCPT.i6)[1:2])

Now you can merge them into a data frame (you definitely need a data frame than a matrix, because columns of z1 are numeric while columns of z2 are character) via:

data.frame(z2, z1)

Reproducible example

x <- array(1:18, dim = c(3L, 3L, 2L), dimnames = list(
           c("Low", "Medium", "High"), c("Low", "Medium", "High"), c("Yes", "No")))

#, , Yes
#
#       Low Medium High
#Low      1      4    7
#Medium   2      5    8
#High     3      6    9
#
#, , No
#
#       Low Medium High
#Low     10     13   16
#Medium  11     14   17
#High    12     15   18

z1 <- apply(x, 3L, c)
## z1 <- matrix(x, ncol = 2L, dimnames = list(NULL, dimnames(x)[[3]]))
z2 <- expand.grid(dimnames(x)[1:2])
data.frame(z2, z1)

#    Var1   Var2 Yes No
#1    Low    Low   1 10
#2 Medium    Low   2 11
#3   High    Low   3 12
#4    Low Medium   4 13
#5 Medium Medium   5 14
#6   High Medium   6 15
#7    Low   High   7 16
#8 Medium   High   8 17
#9   High   High   9 18

Solution 2

An alternative using reshape2 would be

x <- array(1:18, dim = c(3L, 3L, 2L), dimnames = list(
           c("Low", "Medium", "High"), 
           c("Low", "Medium", "High"), 
           c("Yes", "No")))

library(reshape2)
df <- dcast(melt(x), Var1+Var2~Var3) 
df

     Var1   Var2 Yes No
1    Low    Low   1 10
2    Low Medium   4 13
3    Low   High   7 16
4 Medium    Low   2 11
5 Medium Medium   5 14
6 Medium   High   8 17
7   High    Low   3 12
8   High Medium   6 15
9   High   High   9 18
Share:
11,165
amisos55
Author by

amisos55

Updated on June 21, 2022

Comments

  • amisos55
    amisos55 almost 2 years

    I have an array, including two proficiency variables (theta0, theta1) over an item (Yes, No) called "comp". This needs to be converted to one matrix. Is there any way that I could convert a matrix like the one at the bottom?

    My array looks like this:

    >priCPT.i6
    
     , , comp = Yes
    
     theta1
    theta0       Low       Med      High
      Low  0.8377206 0.6760511 0.4576021
      Med  0.6760511 0.4576021 0.2543239
      High 0.4576021 0.2543239 0.1211734
    
    , , comp = No
    
      theta1
    theta0       Low       Med      High
      Low  0.1622794 0.3239489 0.5423979
      Med  0.3239489 0.5423979 0.7456761
      High 0.5423979 0.7456761 0.8788266
    
    attr(,"class")
    [1] "CPA"   "array"
    

    I apologize, I could not produce something that you could play with. I am looking for something like:

    theta0   theta1   Yes        No
    Low      Low      0.8377206  0.1622794
    Low      Med      ..         ..
    Low      High     ..         ..
    Med      Low      ..         ..
    Med      Med      ..         ..
    Med      High     ..         ..
    High     Low      ..         ..
    High     Med      ..         ..
    High     High     ..         ..
    

    Regards...

  • amisos55
    amisos55 over 7 years
    Thanks for your fast and accurate reply. This totally answered my question. I really appreciated. Have a great day.!
  • user20650
    user20650 over 7 years
    ah I see. I initially thought of using as.data.frame.table(x): but I couldnt see a nice way to apply appropriately, only dcast(as.data.frame.table(x), Var1 + Var2 ~ Var3, value.var="Freq") which will not be fast
  • rawr
    rawr over 7 years
    ftable(x) would be best if it returned something useful. or dd <- data.frame(as.table(x)); reshape(dd, dir = 'w', idvar = names(dd)[1:2], timevar = names(dd)[3])
  • gfgm
    gfgm over 7 years
    ah sorry didn't see your comment re: dcast approach
  • amisos55
    amisos55 over 7 years
    Thanks for your helpful entry.
  • amisos55
    amisos55 over 7 years
    No, I accepted your answer. Do not know what happened. Check one more time