R中多列的密集排名

时间:2018-10-04 22:29:26

标签: r dplyr

如何获得数据框中多列的密集排名?例如,

# 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

我的黑客方法适用于此特定数据集:

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

但是必须有一个更通用的解决方案,也许使用诸如dense_rank()row_number()之类的函数。但是我为此感到挣扎。

dplyr解决方案是理想的。

2 个答案:

答案 0 :(得分:6)

发布后,我想我找到了解决方法here。就我而言,应该是:

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

但是,如果您有更好的解决方案,请分享。

答案 1 :(得分:5)

data.table

data.table覆盖了frank()

library(data.table)    
frank(df, x,y, ties.method = 'min')

[1]  1  2  3  4  5  5  5  8  9 10

您可以df$r <- frank(df, x,y, ties.method = 'min')添加为新列。

tidyr / dplyr

另一种方法(虽然比较笨拙)是使用tidyr::unite将列折叠为一个加号dplyr::dense_rank

library(tidyverse)

df %>%

  # add a single column with all the info
  unite(xy, x, y) %>%
  cbind(df) %>%

  # dense rank on that
  mutate(r = dense_rank(xy)) %>%

  # now drop the helper col
  select(-xy)