Reputation: 11
I am trying to make a column which will rank x, grouped by names.
names <- rep(c("Ben", "Joe", "Karen", "Joan"), times = 4)
set.seed(1)
x <- sample((1:10), 16, replace = TRUE)
learnrank <- data.frame(names,x)
The I used the tapply function:
learnrank$rank <-
tapply(learnrank$x, learnrank$names,
rank, ties.method = "first")
learnrank
names x rank
<chr> <int> <list>
Ben 3 <int [4]>
Joe 4 <int [4]>
Karen 6 <int [4]>
Joan 10 <int [4]>
Ben 3 <int [4]>
Joe 9 <int [4]>
Karen 10 <int [4]>
Joan 7 <int [4]>
Ben 7 <int [4]>
Joe 1 <int [4]>
What I would like is this below, where we rank all Ben scores from 1:4, Joe's scores from 1:4, etc.
names x rank
<chr> <int> <list>
Ben 3 1
Joe 4 2
Karen 6 2
Joan 10 4
Ben 3 2
Joe 9 4
Karen 10 4
Joan 7 3
Ben 7 3
Joe 1 1
Does anyone have any suggestions?
Regards
Kevin
Upvotes: 0
Views: 83
Reputation: 39657
You can use ave
instead of tapply
like:
learnrank$rank <- ave(learnrank$x, learnrank$names,
FUN=function(x) rank(x, ties.method = "first"))
learnrank
# names x rank
#1 Ben 9 4
#2 Joe 4 1
#3 Karen 7 3
#4 Joan 1 1
#5 Ben 2 2
#6 Joe 7 3
#7 Karen 2 1
#8 Joan 3 2
#9 Ben 1 1
#10 Joe 5 2
#11 Karen 5 2
#12 Joan 10 4
#13 Ben 6 3
#14 Joe 10 4
#15 Karen 7 4
#16 Joan 9 3
Upvotes: 2
Reputation: 388907
You can order the data and assign row number for each name
.
This can be done in base R :
learnrank <- learnrank[do.call(order, learnrank), ]
learnrank$rank <- with(learnrank, ave(x, names, FUN = seq_along))
Or using dplyr
:
library(dplyr)
learnrank %>%
arrange_all() %>%
group_by(names) %>%
mutate(row = row_number())
Upvotes: 2
Reputation: 16978
Using dplyr
:
learnrank %>%
group_by(names) %>%
mutate(rank=rank(x))
gives you
# A tibble: 16 x 3
# Groups: names [4]
names x rank
<fct> <int> <dbl>
1 Ben 9 4
2 Joe 4 1
3 Karen 7 3.5
4 Joan 1 1
5 Ben 2 2
6 Joe 7 3
7 Karen 2 1
8 Joan 3 2
9 Ben 1 1
10 Joe 5 2
11 Karen 5 2
12 Joan 10 4
13 Ben 6 3
14 Joe 10 4
15 Karen 7 3.5
16 Joan 9 3
With the argument ties.method
you can handle the tie of ranks. Choosing ties.method="first"
is equivalent to
learnrank %>%
group_by(names) %>%
mutate(rank=row_number(x))
Upvotes: 1
Reputation: 173793
Here's a dplyr solution:
library(dplyr)
learnrank %>%
group_by(names) %>%
mutate(x = sort(x), rank = order(-x)) %>%
arrange(names)
#> # A tibble: 16 x 3
#> # Groups: names [4]
#> names x rank
#> <fct> <int> <int>
#> 1 Ben 1 4
#> 2 Ben 2 3
#> 3 Ben 6 2
#> 4 Ben 9 1
#> 5 Joan 1 4
#> 6 Joan 3 3
#> 7 Joan 9 2
#> 8 Joan 10 1
#> 9 Joe 4 4
#> 10 Joe 5 3
#> 11 Joe 7 2
#> 12 Joe 10 1
#> 13 Karen 2 3
#> 14 Karen 5 4
#> 15 Karen 7 2
#> 16 Karen 7 1
Upvotes: 2