# [R] Second largest element from each matrix row

Peter Ehlers ehlers at ucalgary.ca
Tue Apr 26 18:36:47 CEST 2011

```On 2011-04-26 09:11, William Dunlap wrote:
> A different approach is to use order() to sort
> first by row number and then break the ties by
> value.  It is quick when there are lots of short
> rows.

Bill,

That's what Dmitris did, too; his solution falls between
f3 and f4. Unless speed were paramount, I would choose
Peter D's (f4) for its simplicity and transparency.

I kind of figured that you'd do your magic and pull
out a speed demon.

Peter Ehlers

>
>> f1<- function (x)
> +    apply(x, 1, function(row) sort(row, decreasing = TRUE)[2])
>> f2<- function (x)
> +     -apply(-x, 1, function(row) sort.int(row, partial = 2)[2])
>> f3<- function (x)
> + {
> +     # order by row number then by value
> +     y<- t(x)
> +     array(y[order(col(y), y)], dim(y))[nrow(y) - 1, ]
> + }
>> f4<- function (x)
> +     apply(x, 1, function(row) max(row[-which.max(row)]))
>> x<- matrix(runif(1e5*6), nrow=1e5)
>> library(rbenchmark)
>> benchmark(r1<- f1(x), r2<- f2(x), r3<- f3(x), r4<- f4(x),
> +     replications=5, columns=c("test","replications","elapsed"),
> order="elapsed")
>           test replications elapsed
> 3 r3<- f3(x)            5    1.08
> 4 r4<- f4(x)            5   12.59
> 2 r2<- f2(x)            5   23.19
> 1 r1<- f1(x)            5   59.54
>> identical(r1,r2)&&  identical(r1, r3)&&  identical(r1, r4)
> [1] TRUE
>
> Bill Dunlap
> Spotfire, TIBCO Software
> wdunlap tibco.com
>
>> -----Original Message-----
>> From: r-help-bounces at r-project.org
>> [mailto:r-help-bounces at r-project.org] On Behalf Of peter dalgaard
>> Sent: Tuesday, April 26, 2011 8:13 AM
>> To: David Winsemius
>> Cc: r-help at r-project.org
>> Subject: Re: [R] Second largest element from each matrix row
>>
>>
>> On Apr 26, 2011, at 14:36 , David Winsemius wrote:
>>
>>>
>>> On Apr 26, 2011, at 8:01 AM, Lars Bishop wrote:
>>>
>>>> Hi,
>>>>
>>>> I need to extract the second largest element from each row of a
>>>> matrix. Below is my solution, but I think there should be
>> a more efficient
>>>> way to accomplish the same, or not?
>>>>
>>>>
>>>> set.seed(1)
>>>> a<- matrix(rnorm(9), 3 ,3)
>>>> sec.large<- as.vector(apply(a, 1, order, decreasing=T)[2,])
>>>> ans<- sapply(1:length(sec.large), function(i) a[i, sec.large[i]])
>>>> ans
>>>
>>> There are probably many but this one is reasonably compact,
>>>
>>>> ans2<- apply(a, 1, function(i) sort(i)[ dim(a)[2]-1])
>>>> ans2
>>>
>>> Refreshing my mail client proves I was right about many
>> solutions, but this is the first (so far) to use the dim attribute.
>>
>> Anything with sort() or order() will have complexity
>> O(n*log(n)) or worse (n is the number of columns), whereas
>> finding the k-th largest element has complexity O(k*n).
>>
>> For moderate n, this may be unimportant, but you could
>> potentially find a speedup using
>>
>> sort.int(i, decreasing=TRUE, partial=2)[2]
>>
>> or
>>
>> max(i[-which.max(i)])
>>
>> --
>> Peter Dalgaard
>> Center for Statistics, Copenhagen Business School
>> Solbjerg Plads 3, 2000 Frederiksberg, Denmark
>> Phone: (+45)38153501
>> Email: pd.mes at cbs.dk  Priv: PDalgd at gmail.com
>>
>> ______________________________________________
>> R-help at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
>>
>
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help