# Why is this simple ave function not working

I am using the following code and data:

> d <- data.frame(year = rep(2000:2002, each = 3), count = round(runif(9, 0, 20)))
> d
year count
1 2000     1
2 2000     4
3 2000     4
4 2001    14
5 2001     8
6 2001    15
7 2002    10
8 2002    14
9 2002    20
>
> with(d, ave(count, year, sum))
Error in unique.default(x) : unique() applies only to vectors

I tried:

> with(d, ave(count, list(year), sum))
Error in unique.default(x) : unique() applies only to vectors
> with(d, ave(count, list('year'), sum))
Error in unique.default(x) : unique() applies only to vectors
>
> with(d, ave(count, 'year', sum))
Error in unique.default(x) : unique() applies only to vectors

> with(d, ave('count', 'year', sum))
Error in unique.default(x) : unique() applies only to vectors
> ave(d\$count, d\$year, sum)
Error in unique.default(x) : unique() applies only to vectors

> ave(d\$count, factor(d\$year), sum)
Error in unique.default(x) : unique() applies only to vectors

> ave(d\$count, unique(d\$year), sum)
Error in unique.default(x) : unique() applies only to vectors

> ave(d\$count, factor(unique(d\$year)), sum)
Error in unique.default(x) : unique() applies only to vectors
> ave(d\$count, as.factor(unique(d\$year)), sum)
Error in unique.default(x) : unique() applies only to vectors

The following works:

> unique(d\$count)
[1]  1  4 14  8 15 10 20
> unique(d\$year)
[1] 2000 2001 2002

tapply, aggregate and work:

> with(d, tapply(count, year, mean))
2000     2001     2002
3.00000 12.33333 14.66667

> with(d, aggregate(count, list(year), mean))
Group.1        x
1    2000  3.00000
2    2001 12.33333
3    2002 14.66667

> with(d, by(count, year, mean))
year: 2000
[1] 3
-------------------------------------------------------------------------------------------------
year: 2001
[1] 12.33333
-------------------------------------------------------------------------------------------------
year: 2002
[1] 14.66667

Why is there an error 'unique () only applies to vectors' and how can I use the ave function here?

+3

source to share

It's a bit subtle, and I think the best documentation of this actually is about defining the R language to match the arguments :

The first thing that happens in evaluating a function is the overlap of formal to actual or supplied arguments. This is done using a three-pass process:

• Exact tag match. For each assigned list argument, the formal arguments are searched for an element whose name exactly matches. The mistake is that the same formal argument corresponds to several actions, or vice versa.

• Partial tag matching. Each remaining argument is compared to the rest of the formal arguments using partial matches. If the name of the supplied argument matches the name of the first part of the formal argument, then the two arguments are considered to be matched. It is a mistake to have several partial matches. Note that if f <- function (fumble, fooey) fbody, then f (f = 1, fo = 2) is illegal even though only the 2nd actual argument matches fooey. f (f = 1, fooey = 2) is legal, although the second argument matches exactly and is discarded for partial matching. If formal arguments contain "... then the partial match applies only to the arguments that precede it.

• Coordination of positions. Any unsurpassed formal arguments are associated with unnamed arguments, in order. If there is a "..." argument, it will take over the remaining arguments, flagged or not.

So this is the result of the special nature of the argument

. It is, in a sense, "greedy", unless you are more explicit and use named arguments. The reason it doesn't appear elsewhere is because

it is usually the last (or almost the last) argument, so you often don't run into this kind of confusing behavior when using positional matching.

+5

source

All Articles