Etienne Low-Décarie
Etienne Low-Décarie

Reputation: 13443

How to get a data.frame into a multidimensional array in R?

I am looking for a more versatile way to get from a data.frame to a multidimensional array.

I would like to be able to create as many dimensions as needed from as many variables in the data frame as desired.

Currently, the method has to be tailored to each data.frame, requires subletting to form a vector.

I would love something along the melt/cast methods in plyr.

   data<-data.frame(coord.name=rep(1:10, 2),
             x=rnorm(20),
             y=rnorm(20),
             ID=rep(c("A","B"), each=10))


    data.array<-array(dim=c(10, 2, length(unique(data$ID))))

    for(i in 1:length(unique(data$ID))){
      data.array[,1,i]<-data[data$ID==unique(data$ID)[i],"x"]
      data.array[,2,i]<-data[data$ID==unique(data$ID)[i],"y"]
    }

data.array
, , 1

      [,1] [,2]
 [1,]    1    1
 [2,]    3    3
 [3,]    5    5
 [4,]    7    7
 [5,]    9    9
 [6,]    1    1
 [7,]    3    3
 [8,]    5    5
 [9,]    7    7
[10,]    9    9

, , 2

      [,1] [,2]
 [1,]    2    2
 [2,]    4    4
 [3,]    6    6
 [4,]    8    8
 [5,]   10   10
 [6,]    2    2
 [7,]    4    4
 [8,]    6    6
 [9,]    8    8
[10,]   10   10

Upvotes: 7

Views: 6777

Answers (2)

Josh O&#39;Brien
Josh O&#39;Brien

Reputation: 162311

You may have had trouble applying the reshape2 functions for a somewhat subtle reason. The difficulty was that your data.frame has no column that can be used to direct how you want to arrange the elements along the first dimension of an output array.

Below, I explicitly add such a column, calling it "row". With it in place, you can use the expressive acast() or dcast() functions to reshape the data in any way you choose.

library(reshape2)

# Use this or some other method to add a column of row indices.
data$row <- with(data, ave(ID==ID, ID, FUN = cumsum))

m <- melt(data, id.vars = c("row", "ID"))
a <- acast(m, row ~ variable ~ ID)

a[1:3, , ]
# , , A
# 
#   x y
# 1 1 1
# 2 3 3
# 3 5 5
#
# , , B
# 
#   x y
# 1 2 2
# 2 4 4
# 3 6 6

Upvotes: 7

mdsumner
mdsumner

Reputation: 29477

I think this is right:

array(unlist(lapply(split(data, data$ID), function(x) as.matrix(x[ , c("x", "y")]))), c(10, 2, 2))

Upvotes: 4

Related Questions