Reputation: 715
I have the following data frame called surge
:
MeshID StormID Rate Surge Wind
1 1412 1.0000E-01 0.01 0.0
2 1412 1.0000E-01 0.03 0.0
3 1412 1.0000E-01 0.09 0.0
4 1412 1.0000E-01 0.12 0.0
5 1412 1.0000E-01 0.02 0.0
6 1412 1.0000E-01 0.02 0.0
7 1412 1.0000E-01 0.07 0.0
1 1413 1.0000E-01 0.06 0.0
2 1413 1.0000E-01 0.02 0.0
3 1413 1.0000E-01 0.05 0.0
I used the following code to find the max value of surge per storm:
MaxSurge <- data.frame(tapply(surge[,4], surge[,2], max))
It returns:
1412 0.12
1413 0.06
This is great, except I'd also like it to include the MeshID
value at the point where the surge is the maximum. I know I can probably use which.max
, but I can't quite figure out how to put this in action. I'm VERY new to R programming.
Upvotes: 22
Views: 22698
Reputation: 165
here is another data.table solution, but not relying on .SD (thus 10x faster)
surge[,grp.ranks:=rank(-1*surge,ties.method='min'),by=StormID]
surge[grp.ranks==1,]
Upvotes: 13
Reputation: 115415
And a data.table
solution for coding elegance
library(data.table)
surge <- as.data.table(surge)
surge[, .SD[which.max(surge)], by = StormID]
Upvotes: 14
Reputation: 66844
If you have 2 data.points at the maximum, which.max
will only refer to the first one. A more complete solution would involve rank
:
# data with a tie for max
surge <- data.frame(MeshID=c(1:7,1:4),StormID=c(rep(1412,7),
rep(1413,4)),Surge=c(0.01,0.03,0.09,0.12,0.02,0.02,0.07,0.06,0.02,0.05,0.06))
# compute ranks
surge$rank <- ave(-surge$Surge,surge$StormID,FUN=function(x) rank(x,ties.method="min"))
# subset on the rank
subset(surge,rank==1)
MeshID StormID Surge rank
4 4 1412 0.12 1
8 1 1413 0.06 1
11 4 1413 0.06 1
Upvotes: 7
Reputation: 176688
Here's a plyr solution, just because someone will say it if I don't...
R> ddply(surge, "StormID", function(x) x[which.max(x$Surge),])
MeshID StormID Rate Surge Wind
1 4 1412 0.1 0.12 0
2 1 1413 0.1 0.06 0
Upvotes: 6