[R] Reshaping matrix of vectors as dataframe

David Winsemius dwinsemius at comcast.net
Sun Jan 31 18:47:21 CET 2010


On Jan 31, 2010, at 9:53 AM, Oliver Gondring wrote:

> Dear R people,
>
> I have to deal with the output of a function which comes as a matrix  
> of vectors.

If that is so, then the object below does not represent it, because  
that is a matrix of _lists_.

> You can reproduce the structure as given below:
>
> x <- list(c(1,2,4),c(1,3,5),c(0,1,0),
>          c(1,3,6,5),c(3,4,4,4),c(0,1,0,1),
>          c(3,7),c(1,2),c(0,1))
> data <- matrix(x,byrow=TRUE,nrow=3)
> colnames(data) <- c("First", "Length", "Value")
> rownames(data) <- c("Case1", "Case2", "Case3")
>
> > data
>      First     Length    Value
> Case1 Numeric,3 Numeric,3 Numeric,3
> Case2 Numeric,4 Numeric,4 Numeric,4
> Case3 Numeric,2 Numeric,2 Numeric,2
>
> > data["Case1",]
> $First
> [1] 1 2 4
>
> $Length
> [1] 1 3 5
>
> $Value
> [1] 0 1 0
> --------------------
>
> My goal now is to break the three vectors of each row of the matrix  
> into their elements, assigning each element to a certain  
> "Sequence" (which I want to be numbered according to the position of  
> the corresponding values within the vectors), reshaping the whole as  
> a data frame like this:

This is close to what you specify:

 > apply(data, 1, function(.x) cbind(1:length(.x$First), sapply(.x,  
function(.y) return(.y ) ) ) )
$Case1
        First Length Value
[1,] 1     1      1     0
[2,] 2     2      3     1
[3,] 3     4      5     0

$Case2
        First Length Value
[1,] 1     1      3     0
[2,] 2     3      4     1
[3,] 3     6      4     0
[4,] 4     5      4     1

$Case3
        First Length Value
[1,] 1     3      1     0
[2,] 2     7      2     1

And if you do.call(rbind, on the result you would get a matrix but  
loose the case labeling.

Adding the Case labels proved to be a bit of a challenge to me. Maybe  
one of the wizards will take pity on us:

 > sapply(rownames(data),  function(.x) cbind(.x,
# those were the rownames
                 cbind(1:length(data[.x, "First"][[1]]),
# and that was the incremental counter
                sapply(data[.x, ],
#and finally the values which unfortunately get turned into characters
                function(.y) return(.y ) ) ) )  )


$Case1
      .x          First Length Value
[1,] "Case1" "1" "1"   "1"    "0"
[2,] "Case1" "2" "2"   "3"    "1"
[3,] "Case1" "3" "4"   "5"    "0"

$Case2
      .x          First Length Value
[1,] "Case2" "1" "1"   "3"    "0"
[2,] "Case2" "2" "3"   "4"    "1"
[3,] "Case2" "3" "6"   "4"    "0"
[4,] "Case2" "4" "5"   "4"    "1"

$Case3
      .x          First Length Value
[1,] "Case3" "1" "3"   "1"    "0"
[2,] "Case3" "2" "7"   "2"    "1"

(I tried a couple of plyr efforts but that is not a package that I  
have had much success with.)

-- 
David.

>
> Case	Sequence	First	Length	Value
>
> Case1	1		1	1	0
> Case1	2		2	3	1
> Case1	3		4	5	0
>
> Case2	1		1	3	0
> Case2	2		3	4	1
> Case2	3		6	4	0
> Case2	4		5	4	1
>
> Case3	1		3	1	0			
> Case3	2		7	2	1
>
> I suspect that there might be an elegant and not too complicated way  
> to do this with one or several of the functions provided by the  
> 'reshape' package, but due to my lack of experience with R in  
> general, this package in particular and the complexity of the task I  
> wasn't able to figure out how to do it so far.
>
> Every hint or helpful comment is much appreciated!
>
> Oliver
>
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.

David Winsemius, MD
Heritage Laboratories
West Hartford, CT



More information about the R-help mailing list