[R] ave(x, y, FUN=length) produces character output when x is character

Mike Miller mbmiller+l at gmail.com
Thu Dec 25 08:15:28 CET 2014


On Wed, 24 Dec 2014, Bert Gunter wrote:

> You are again misinterpreting because you have not read the docs, 
> although this time I will grant that they are to some extent misleading.
>
> First of all, a matrix _IS_ a vector:
>
>> a <- matrix(1:4, 2,2)
>> a[3] ## vector indexing works because it is a vector
> [1] 3
>
> In fact, a matrix (or array) is a vector with a "dim" attribute. This
> is documented in ?matrix:
>
> "is.matrix returns TRUE if x is a vector and has a "dim" attribute of
> length 2) and FALSE otherwise."

But a vector has no such attribute, so a matrix is not a vector which is 
why you see this:

> a <- matrix(1:4, 2,2)
> is.vector(a)
[1] FALSE

Of course the matrix can be coerced back into a vector just as the vector 
was coerced into a matrix:

> b <- as.vector(a)
> is.vector(b)
[1] TRUE


> Your confusion arises because, despite its name, is.vector() does not 
> actually test whether something "is" a vector (after all these are all 
> abstractions; what it "is" is contents of memory, implemented as a 
> linked list or some such).  ?is.vector tells you:
>
> "is.vector returns TRUE if x is a vector of the specified mode having
> no attributes other than names. It returns FALSE otherwise."

So that means that a vector in R has no attributes other than names.


> An array has a "dim" attribute, so is.vector() returns FALSE on it. But 
> it actually _is_ ("behaves like") a vector (in column major 
> order,actually).

An array is a vector with additional attributes which cause it to be an 
array rather than a vector.  This is why R says FALSE when we query it 
about an array using is.vector().


> Now you may complain that this is confusing and I would agree. Why is it 
> this way? I dunno -- probably due to historical quirks -- evolution is 
> not necessarily orderly. But that's the way it is; that's the way it's 
> documented; and tutorials will tell you about this (that's how I 
> learned). So please stop guessing and intuiting and read the docs to 
> understand how things work.

I don't think it is confusing.  This is the kind of behavior I'm used to 
from other programs like Octave/MATLAB.  A vector is just an ordered list 
of numbers.  Those numbers can be put into matrices or higher-dimensional 
arrays, but they then become something more than just a vector.  A vector 
like 1:4 becomes a 2x2 matrix when we do matrix(1:4, 2,2) such that the 
number 3 which was just the third element before (and still is) is now 
also the [1,2] element of a matrix.  It didn't have that before, back when 
it was a vector, but now that it has become something more than a vector, 
it has that new property.  We can take that away using as.vector().

In many situations the behavior of the R vector and the same values in a 
matrix format will be very different:

> a <- 1:4
> b <- matrix(a, 2,2)
> a %*% a
      [,1]
[1,]   30
> b %*% b
      [,1] [,2]
[1,]    7   15
[2,]   10   22
> b %*% t(b)
      [,1] [,2]
[1,]   10   14
[2,]   14   20
> a %*% t(a)
      [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    2    4    6    8
[3,]    3    6    9   12
[4,]    4    8   12   16

That is not true in ave(), as I showed earlier, because it uses the vector 
ordering of elements in the x matrix or array (what one would get from 
as.vector()) to form the correspondence with the factor.

I get your idea, but I don't think it is correct to say "a matrix is a 
vector."  Rather, I would say that there is a standard way in which one 
can create a one-to-one correspondence between the elements of a matrix of 
given dimensions and the elements of a vector.  I believe this is usually 
called "fortran indexing," or at least that is what it is called in 
Octave.  The same thing is done with vectorization and the vec() operator 
in mathematics:

http://en.wikipedia.org/wiki/Vectorization_(mathematics)

But in math as in computing, we wouldn't say that a matrix *is* a vector. 
If vec(A) = v, that does not mean that A = v.  In R, it looks like 
as.vector() can do what vec() does, and more.

Mike

-- 
Michael B. Miller, Ph.D.
University of Minnesota
http://scholar.google.com/citations?user=EV_phq4AAAAJ



More information about the R-help mailing list