[R] the first and last observation for each subject
Kingsford Jones
kingsfordjones at gmail.com
Mon Jan 5 22:37:30 CET 2009
Here's some more timing's of Bill's function. Although in this
example sapply has a clear performance advantage for smaller numbers
of groups (k) , gm is substantially faster for k >> 1000:
gm <- function(x, group){ # medians by group:
o<-order(group, x)
group <- group[o]
x <- x[o]
changes <- group[-1] != group[-length(group)]
first <- which(c(TRUE, changes))
last <- which(c(changes, TRUE))
lowerMedian <- x[floor((first+last)/2)]
upperMedian <- x[ceiling((first+last)/2)]
median <- (lowerMedian+upperMedian)/2
names(median) <- group[first]
median
}
##
for(k in 10^(1:6)){
group<-sample(1:k, size=100000, replace=TRUE)
x<-rnorm(length(group))*10 + group
cat('number of groups:', k, '\n')
cat('sapply\n')
print(s <- unix.time(sapply(split(x,group), median)))
cat('gm\n')
print(g <- unix.time(-gm(x,group)))
cat(' sapply/gm user ratio:', s[1]/g[1], '\n\n\n')
}
number of groups: 10
sapply
user system elapsed
0.01 0.00 0.01
gm
user system elapsed
0.14 0.00 0.16
sapply/gm user ratio: 0.07142857
number of groups: 100
sapply
user system elapsed
0.02 0.00 0.02
gm
user system elapsed
0.11 0.00 0.09
sapply/gm user ratio: 0.1818182
number of groups: 1000
sapply
user system elapsed
0.11 0.00 0.11
gm
user system elapsed
0.11 0.00 0.11
sapply/gm user ratio: 1
number of groups: 10000
sapply
user system elapsed
1.00 0.00 1.04
gm
user system elapsed
0.10 0.00 0.09
sapply/gm user ratio: 10
number of groups: 1e+05
sapply
user system elapsed
6.24 0.01 6.31
gm
user system elapsed
0.16 0.00 0.17
sapply/gm user ratio: 39
number of groups: 1e+06
sapply
user system elapsed
9.00 0.03 8.92
gm
user system elapsed
0.15 0.00 0.20
sapply/gm user ratio: 60
> R.Version()
$platform
[1] "i386-pc-mingw32"
$arch
[1] "i386"
$os
[1] "mingw32"
$system
[1] "i386, mingw32"
$status
[1] ""
$major
[1] "2"
$minor
[1] "8.0"
$year
[1] "2008"
$month
[1] "10"
$day
[1] "20"
$`svn rev`
[1] "46754"
$language
[1] "R"
$version.string
[1] "R version 2.8.0 (2008-10-20)"
Kingsford Jones
On Mon, Jan 5, 2009 at 10:18 AM, William Dunlap <wdunlap at tibco.com> wrote:
> Arg, the 'sapply(...)' in the function was in the initial
> comment,
> gm <- function(x, group){ # medians by group:
> sapply(split(x,group),median)
> but someone's mailer put a newline before the sapply
> gm <- function(x, group){ # medians by group:
> sapply(split(x,group),median)
> so it got executed, wasting all that time. (Of course the
> same mailer will mess up this message in the same way -
> just delete the sapply() call from gm().)
>
> Bill Dunlap
> TIBCO Software Inc - Spotfire Division
> wdunlap tibco.com
>
>> -----Original Message-----
>> From: hadley wickham [mailto:h.wickham at gmail.com]
>> Sent: Monday, January 05, 2009 9:10 AM
>> To: William Dunlap
>> Cc: gallon.li at gmail.com; R help
>> Subject: Re: [R] the first and last observation for each subject
>>
>> > Another application of that technique can be used to quickly compute
>> > medians by groups:
>> >
>> > gm <- function(x, group){ # medians by group:
>> > sapply(split(x,group),median)
>> > o<-order(group, x)
>> > group <- group[o]
>> > x <- x[o]
>> > changes <- group[-1] != group[-length(group)]
>> > first <- which(c(TRUE, changes))
>> > last <- which(c(changes, TRUE))
>> > lowerMedian <- x[floor((first+last)/2)]
>> > upperMedian <- x[ceiling((first+last)/2)]
>> > median <- (lowerMedian+upperMedian)/2
>> > names(median) <- group[first]
>> > median
>> > }
>> >
>> > For a 10^5 long x and a somewhat fewer than 3*10^4 distinct groups
>> > (in random order) the times are:
>> >
>> >> group<-sample(1:30000, size=100000, replace=TRUE)
>> >> x<-rnorm(length(group))*10 + group
>> >> unix.time(z0<-sapply(split(x,group), median))
>> > user system elapsed
>> > 2.72 0.00 3.20
>> >> unix.time(z1<-gm(x,group))
>> > user system elapsed
>> > 0.12 0.00 0.16
>> >> identical(z1,z0)
>> > [1] TRUE
>>
>> I get:
>>
>> > unix.time(z0<-sapply(split(x,group), median))
>> user system elapsed
>> 2.733 0.017 2.766
>> > unix.time(z1<-gm(x,group))
>> user system elapsed
>> 2.897 0.032 2.946
>>
>>
>> Hadley
>>
>>
>> --
>> http://had.co.nz/
>>
>
> ______________________________________________
> R-help at r-project.org mailing list
> 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.
>
More information about the R-help
mailing list