'I'm having difficulty getting the right data into the matrices of my 4x3x21 array

What I'm having trouble with is I'd like the first row of this matrix (mat.a) to be the first row of matrix 1 in my array, and then the second row to be the first row of matrix 2, etc. Then the first row of mat.b to be the second row of the first matrix in my array, second row of mat. b to be the second row in the second matrix of the array, etc. This trend continues for mat.c. The fourth row of my matrix should be the averages of the values in each column. Also, I'm not allowed to use a for loop

mat.a <- matrix(c(scores$A1, scores$A2, scores$avgA), ncol = 3, 
byrow = FALSE)
mat.b <- matrix(c(scores$B1, scores$B2, scores$avgB), ncol = 3, 
byrow = FALSE)
mat.c <- matrix(c(scores$C1, scores$C2, scores$avgC), ncol = 3, 
byrow = FALSE)

scores.array<- array(c(mat.a,mat.b, mat.c), dim = c(3,3,21))


> dim(mat.a)
[1] 21  3
> dim(scores)
[1] 21 10
> dim(mat.b)
[1] 21  3
> dim(mat.c)
[1] 21  3

scores scores.updated



Solution 1:[1]

Here is a natural (I think) approach to this problem:

  1. Use array to construct an array with A, B, and C lying along the third dimension.
  2. Use aperm to transpose the array so that A, B, and C lie along the first dimension.
  3. Use colMeans to compute means over the first dimension ("columnwise").
  4. Use abind to attach the means to the transposed array.
nms <- c("A1", "A2", "avgA", "B1", "B2", "avgB", "C1", "C2", "avgC")
z <- array(unlist(scores[nms]), dim = c(21L, 3L, 3L))
zz <- aperm(zz, 3:1)
zzz <- abind::abind(zz, colMeans(zz, dims = 1L), along = 1L)
zzz[, , 1:2]
, , 1

         [,1]     [,2]     [,3]
[1,] 28.75775 69.28034 49.01905
[2,] 41.37243 27.43836 34.40540
[3,] 10.28646 89.03502 49.66074
[4,] 26.80555 61.91791 44.36173

, , 2

         [,1]     [,2]     [,3]
[1,] 78.83051 64.05068 71.44060
[2,] 36.88455 81.46400 59.17427
[3,] 43.48927 91.44382 67.46655
[4,] 53.06811 78.98617 66.02714

I have used scores as (very helpfully!) defined by @langtang.

Solution 2:[2]

Try this:

library(tidyverse)
# add the averages 
scores <- scores %>%
  rowwise() %>%
  mutate(avg1 = mean(c_across(ends_with("1"))),
         avg2 = mean(c_across(ends_with("2"))),
         avg3 = mean(c_across(starts_with("avg")))) %>% 
  # relocate the columns
  relocate(ini, A1,B1,C1,avg1, A2,B2,C2,avg2, avgA,avgB,avgC, avg3)

# create scores array
scores.array = array(scores %>% pivot_longer(cols = A1:avg3) %>% pull(value), dim=c(4,3,21))

# add dim names
dimnames(scores.array) = list(c("A","B","C","mean"), c("Midterm", "Final", "mean"), scores$ini)

Output (first two):

> scores.array[,,1:2]
, , ZO

      Midterm    Final     mean
A    28.75775 69.28034 49.01905
B    41.37243 27.43836 34.40540
C    10.28646 89.03502 49.66074
mean 26.80555 61.91791 44.36173

, , UE

      Midterm    Final     mean
A    78.83051 64.05068 71.44060
B    36.88455 81.46400 59.17427
C    43.48927 91.44382 67.46655
mean 53.06811 78.98617 66.02714

Input Data (fake data):

set.seed(123)
scores = data.frame(
  A1 = runif(21)*100,
  A2 = runif(21)*100,
  B1 = runif(21)*100,
  B2 = runif(21)*100,
  C1 = runif(21)*100,
  C2 = runif(21)*100
)

scores <- scores %>% rowwise() %>% 
  mutate(ini = paste0(sample(LETTERS,2), collapse="")) %>% 
  relocate(ini)

scores$avgA = apply(scores[,c("A1","A2")],1,mean)
scores$avgB = apply(scores[,c("B1","B2")],1,mean)
scores$avgC = apply(scores[,c("C1","C2")],1,mean)
  
   ini      A1    A2    B1    B2    C1    C2  avgA  avgB  avgC
   <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1 ZO    28.8   69.3 41.4   27.4  10.3 89.0   49.0  34.4  49.7
 2 UE    78.8   64.1 36.9   81.5  43.5 91.4   71.4  59.2  67.5
 3 HS    40.9   99.4 15.2   44.9  98.5 60.9   70.2  30.0  79.7
 4 JR    88.3   65.6 13.9   81.0  89.3 41.1   76.9  47.4  65.2
 5 JL    94.0   70.9 23.3   81.2  88.6 14.7   82.4  52.3  51.7
 6 BJ     4.56  54.4 46.6   79.4  17.5 93.5   29.5  63.0  55.5
 7 VL    52.8   59.4 26.6   44.0  13.1 30.1   56.1  35.3  21.6
 8 TN    89.2   28.9 85.8   75.4  65.3  6.07  59.1  80.6  35.7
 9 QN    55.1   14.7  4.58  62.9  34.4 94.8   34.9  33.8  64.6
10 VC    45.7   96.3 44.2   71.0  65.7 72.1   71.0  57.6  68.9
# ... with 11 more rows

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mikael Jagan
Solution 2