[R] Determining which.max() within groups

Charles C. Berry ccberry at ucsd.edu
Wed Jun 7 21:06:09 CEST 2017


On Tue, 6 Jun 2017, Morway, Eric wrote:

> Using the dataset below, I got close to what I'm after, but not quite all
> the way there.  Any suggestions appreciated:
>
> Daily <- read.table(textConnection("     Date  wyr        Q
> 1911-04-01 1990 4.530695
> 1911-04-02 1990 4.700596
> 1911-04-03 1990 4.898814
> 1911-04-04 1990 5.097032
> 1911-04-05 1991 5.295250
> 1911-04-06 1991 6.569508
> 1911-04-07 1991 5.861587
> 1911-04-08 1991 5.153666
> 1911-04-09 1992 4.445745
> 1911-04-10 1992 3.737824
> 1911-04-11 1992 3.001586
> 1911-04-12 1992 3.001586
> 1911-04-13 1993 2.350298
> 1911-04-14 1993 2.661784
> 1911-04-16 1993 3.001586
> 1911-04-17 1993 2.661784
> 1911-04-19 1994 2.661784
> 1911-04-28 1994 3.369705
> 1911-04-29 1994 3.001586
> 1911-05-20 1994 2.661784"),header=TRUE)
>
> aggregate(Q ~ wyr, data = Daily, which.max)
>
> # gives:
> #    wyr Q
> # 1 1990 4
> # 2 1991 2
> # 3 1992 1
> # 4 1993 3
> # 5 1994 2
>
> I can 'see' that it is returning the which.max() relative to each
> grouping.  Is there a way to instead return the absolute position (row) of
> the max value within each group.  i.e.:
>
> # Would instead like to have
> #     wyr  Q
> # 1  1990  4
> # 2  1991  6
> # 3  1992  9
> # 4  1993  15
> # 5  1994  18
>
> The icing on the cake would be to get the Julien Day corresponding to the
> date on which each year's maximum occurs?
>


Like this:

> which.max.by.wyr <- with(Daily, which( ave( Q, wyr, FUN=max) == Q))
> cbind( Daily[ which.max.by.wyr, ], index=which.max.by.wyr )
          Date  wyr        Q index
4  1911-04-04 1990 5.097032     4
6  1911-04-06 1991 6.569508     6
9  1911-04-09 1992 4.445745     9
15 1911-04-16 1993 3.001586    15
18 1911-04-28 1994 3.369705    18

If there are ties in Q and you do not want more than one max value listed, 
you can add a litle fuzz to randomly pick one. i.e.

> fuzz <- runif(nrow(Daily), 0, 1e-10)
> which.max.by.wyr <- with(Daily, which(ave(Q+fuzz,wyr,FUN=max)==Q+fuzz))


If you want the first tied value, then sort fuzz before determining 
which.max.by.wyr.

HTH,

Chuck



More information about the R-help mailing list