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

William Dunlap wdunlap at tibco.com
Wed Dec 24 22:34:02 CET 2014


   > ave( as.character(1:5), gl(2,2,5), FUN=length )
   [1] "3" "3" "2" "2" "3"The output has character type, but it is supposed
to be a collection of vector lengths.

ave() uses its first argument, 'x', to set the length of its output and to
make
an initial guess at the type of its output.  The return value of FUN can
alter
the type, but only in an 'upward' direction where
logical<integer<numeric<complex
<character<list.  (This is the same rule that x[i]<-newvalue uses.)

As currently written, ave also lets FUN(xi) return a vector the length of
xi,
not just a single value.  E.g.,
  > ave(105:101, c("A","A","B","A","B"), FUN=sort)
  [1] 102 104 101 105 103
  > ave(105:101, c("A","A","B","A","B"), FUN=function(xi)xi-mean(xi))
  [1]  1.3333333  0.3333333  1.0000000 -1.6666667 -1.0000000

I don't know what the docs say about that, but I often find that more
useful than
having it repeat the output of mean(xi).


Bill Dunlap
TIBCO Software
wdunlap tibco.com

On Wed, Dec 24, 2014 at 11:30 AM, Mike Miller <mbmiller+l at gmail.com> wrote:
>
> R 3.0.1 on Linux 64...
>
> I was working with someone else's code.  They were using ave() in a way
> that I guess is nonstandard:  Isn't FUN always supposed to be a variant of
> mean()?  The idea was to count for every element of a factor vector how
> many times the level of that element occurs in the factor vector.
>
>
> gl() makes a factor:
>
>  gl(2,2,5)
>>
> [1] 1 1 2 2 1
> Levels: 1 2
>
>
> ave() applies FUN to produce the desired count, and it works:
>
>  ave( 1:5, gl(2,2,5), FUN=length )
>>
> [1] 3 3 2 2 3
>
>
> The elements of the first vector are irrelevant because they are only
> counted, so we should get the same result if it were a character vector,
> but we don't:
>
>  ave( as.character(1:5), gl(2,2,5), FUN=length )
>>
> [1] "3" "3" "2" "2" "3"
>
> The output has character type, but it is supposed to be a collection of
> vector lengths.
>
>
> Two questions:
>
> (1) Is that a bug in ave()?  It certainly is unexpected.
>
> (2) What is the best way to do this sort of thing?
>
> The truth is that we start with a character vector and we want to create
> an integer vector that tells us for every element of the character vector
> how many times that string occurs.  Here are two vectors of length 6 that
> should give the same result:
>
>  intvec <- c(4,5,6,5,6,6)
>> charvec <- c("A","B","C","B","C","C")
>>
>
> The code was used like this with integer vectors and it seemed to work:
>
>  ave( intvec, intvec, FUN=length )
>>
> [1] 1 2 3 2 3 3
>
> When a character vector came along, it would fail by producing a character
> vector as output:
>
>  ave( charvec, charvec, FUN=length )
>>
> [1] "1" "2" "3" "2" "3" "3"
>
> This seems more appropriate, and it might always work, but is it OK?:
>
>  ave( rep(1, length(charvec)), as.factor(charvec), FUN=sum )
>>
> [1] 1 2 3 2 3 3
>
> I suspect that ave() isn't the best choice, but what is the best way to do
> this?
>
>
> Thanks in advance.
>
> Mike
>
> ______________________________________________
> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
> 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.
>

	[[alternative HTML version deleted]]



More information about the R-help mailing list