Search code examples
rdplyr

Dense Rank by Multiple Columns in R


How can I get a dense rank of multiple columns in a dataframe? For example,

# I have:
df <- data.frame(x = c(1,1,1,1,2,2,2,3,3,3), 
                 y = c(1,2,3,4,2,2,2,1,2,3))
# I want:
res <- data.frame(x = c(1,1,1,1,2,2,2,3,3,3), 
                  y = c(1,2,3,4,2,2,2,1,2,3),
                  r = c(1,2,3,4,5,5,5,6,7,8))
res
   x y z
1  1 1 1
2  1 2 2
3  1 3 3
4  1 4 4
5  2 2 5
6  2 2 5
7  2 2 5
8  3 1 6
9  3 2 7
10 3 3 8

My hack approach works for this particular dataset:

df %>%
  arrange(x,y) %>%
  mutate(r = if_else(y - lag(y,default=0) == 0, 0, 1)) %>%
  mutate(r = cumsum(r))

But there must be a more general solution, maybe using functions like dense_rank() or row_number(). But I'm struggling with this.

dplyr solutions are ideal.


Solution

  • I think I found a solution here. In my case, it would be:

    mutate(df, r = dense_rank(interaction(x,y,lex.order=T)))