Albert
Albert

Reputation: 197

From dataframe to array, by row

I have a dataframe "df", and I would like to transform it into an array BY ROW, for example:

> df
    x  y
1   1 21
2   2 22
3   3 23
4   4 24
5   5 25
6   6 26
7   7 27
8   8 28

#Into this array:

> array.df
 , , 1

     [,1] [,2] [,3] [,4]
[1,]   1   21   2   22
[2,]   3   23   4   24

, , 2

     [,1] [,2] [,3] [,4]
[1,]   5   25   6   26
[2,]   7   27   8   28

Can anyone help me with the code? Thanks.

Upvotes: 1

Views: 1452

Answers (4)

thelatemail
thelatemail

Reputation: 93803

Just thought of a simpler base R answer for this using some array manipulation:

apply(array(t(df), dim=c(4,2,2)), c(1,3), t)

#, , 1
#
#     [,1] [,2] [,3] [,4]
#[1,]    1   21    2   22
#[2,]    3   23    4   24
#
#, , 2
#
#     [,1] [,2] [,3] [,4]
#[1,]    5   25    6   26
#[2,]    7   27    8   28

Use some matrix trickery to fill by row and then reshape again. sapply's simplify="array" ensures the array output:

sapply(
  split(df, rep(1:2,each=nrow(df)/2)),
  function(x) matrix(c(matrix(unlist(x),byrow=TRUE,ncol=2)),nrow=2), 
  simplify="array"
)

#, , 1
#
#     [,1] [,2] [,3] [,4]
#[1,]    1   21    2   22
#[2,]    3   23    4   24
#
#, , 2
#
#     [,1] [,2] [,3] [,4]
#[1,]    5   25    6   26
#[2,]    7   27    8   28

Upvotes: 0

Adam Hoelscher
Adam Hoelscher

Reputation: 1892

Using only the base package:

df <- data.frame(x = 1:8, y = 21:28)

array.df <- array(
  data = as.vector(t(df)),
  dim = c(4,2,2))

array.df <- aperm(a = array.df, perm = c(2,1,3))

print(array.df)

Upvotes: 1

KTWillow
KTWillow

Reputation: 307

Here is another not so elegant solution:

df <- data.frame(x=1:8, y=21:28)
vec <- as.vector(t(df))               # transpose df and then turn into a single vector 
arr <- array(vec, dim=c(4,2,2))       # create array with first 2 dimensions transposed
lis <- lapply(1:2, function(x) { t(arr[,,x]) }) # transpose the first 2 dimensions
array(do.call(cbind, lis), c(2,4,2))  # convert back to array format

, , 1

     [,1] [,2] [,3] [,4]
[1,]    1   21    2   22
[2,]    3   23    4   24

, , 2

     [,1] [,2] [,3] [,4]
[1,]    5   25    6   26
[2,]    7   27    8   28

Upvotes: 1

Abdou
Abdou

Reputation: 13274

Quite an ugly solution, but it gets the job done. Maybe someone else has a better way of doing this. In the meantime, it should do.

install.packages("reshape2")
library("reshape2")

df

  x  y
1 1 21
2 2 22
3 3 23
4 4 24
5 5 25
6 6 26
7 7 27
8 8 28

myarray <- array(cbind(matrix(melt(t(df))[1:8,3],byrow = T, ncol = 4),matrix(melt(t(df))[9:16,3],byrow = T, ncol = 4)), c(2,4,2))

, , 1
     [,1] [,2] [,3] [,4]
[1,]    1   21    2   22
[2,]    3   23    4   24

, , 2
     [,1] [,2] [,3] [,4]
[1,]    5   25    6   26
[2,]    7   27    8   28

I will try and explain:

The idea is to transpose the data frame with t() and then melt it using the melt() function from the reshape2 package. Upon reshaping the data, you want to grab the 3rd column and then create two matrices from it by row. Then, you will need to cbind those matrices into one matrix. And finally, use that matrix to get the array you want with dimension c(2,4,2).

I hope this makes sense.

Upvotes: 1

Related Questions