开发者

rbind() returning an odd result

This has all the signs of being something that's so trivially stupid that I'll regret asking it in a public forum, but I've now stumped a few people on it so c'est la vie.

I'm running the following block of code, and not getting the result that I expect:

zz <- list(a=list('a', 'b', 'c', 'd'), b=list('f', 'g', '2', '1'),
           c=list('t', 'w', 'x', '6'))
padMat <- do.call('cbind', zz)
headMat <- matrix(c(col开发者_运维问答names(padMat), rep('foo', ncol(padMat))), nrow=2, byrow=TRUE)
rbind(headMat, padMat)

I had expected:

a    b    c
foo  foo  foo
a    f    t
b    g    w
c    2    x
d    1    6

Instead I'm getting:

a    b    c
a    f    t 
b    g    w
c    2    x
d    1    6
NULL NULL NULL

It appears that it's filling in the upper part of the rbind by row, and then adding a row of NULL values at the end.

A couple of notes:

  • This works AOK as long as headMat is a single row

  • To double check, I also got rid of the dimnames for padMat, this wasn't affecting things

  • Another thought was that it somehow had to do with the byrow=TRUE, but the same behavior happens if you take that out


padMat is a list (with a dim attribute), not what you usually think of as a matrix.

> padMat <- do.call('cbind', zz)
> str(padMat)
List of 12
 $ : chr "a"
 $ : chr "b"
 $ : chr "c"
 $ : chr "d"
 $ : chr "f"
 $ : chr "g"
 $ : chr "2"
 $ : chr "1"
 $ : chr "t"
 $ : chr "w"
 $ : chr "x"
 $ : chr "6"
 - attr(*, "dim")= int [1:2] 4 3
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:3] "a" "b" "c"

I suspect you want something like:

> padMat <- do.call(cbind,lapply(zz,c,recursive=TRUE))
> str(padMat)
 chr [1:4, 1:3] "a" "b" "c" "d" "f" "g" "2" "1" "t" "w" ...
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:3] "a" "b" "c"

The lesson here is, "str is your friend." :)


The problem appears to stem from the fact that padMat is a strange matrix. R reports that is a list of 12 with dimensions:

R> str(padMat)
List of 12
 $ : chr "a"
 $ : chr "b"
 $ : chr "c"
 $ : chr "d"
 $ : chr "f"
 $ : chr "g"
 $ : chr "2"
 $ : chr "1"
 $ : chr "t"
 $ : chr "w"
 $ : chr "x"
 $ : chr "6"
 - attr(*, "dim")= int [1:2] 4 3
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:3] "a" "b" "c"

That appears to be the source of the problem, as recasting as a matrix works:

R> rbind(headMat, matrix(unlist(padMat), ncol = 3))
     [,1]  [,2]  [,3] 
[1,] "a"   "b"   "c"  
[2,] "foo" "foo" "foo"
[3,] "a"   "f"   "t"  
[4,] "b"   "g"   "w"  
[5,] "c"   "2"   "x"  
[6,] "d"   "1"   "6"


Others have correctly pointed out the fact that padMat had mode list, which if you look at the docs for rbind and cbind, is bad:

In the default method, all the vectors/matrices must be atomic (see vector) or lists.

That's why the do.call works, since the elements of zz are themselves lists. If you change the definition of zz to the following:

zz <- list(a=c('a', 'b', 'c', 'd'), b=c('f', 'g', '2', '1'),
       c=c('t', 'w', 'x', '6'))

the code works as expected.

More insight can be had, I think, from this nugget also in the docs for rbind and cbind:

The type of a matrix result determined from the highest type of any of the inputs 
 in the hierarchy raw < logical < integer < real < complex < character < list .
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜