R中多列的密集排名

low*_*rul 5 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
Run Code Online (Sandbox Code Playgroud)

我的hack方法适用于这个特定的数据集:

df %>%
  arrange(x,y) %>%
  mutate(r = if_else(y - lag(y,default=0) == 0, 0, 1)) %>%
  mutate(r = cumsum(r))
Run Code Online (Sandbox Code Playgroud)

但必须有一个更通用的解决方案,可能使用像dense_rank()或等函数row_number().但我正在努力解决这个问题.

dplyr 解决方案是理想的

low*_*rul 8

发布后,我想我在这里找到了解决方案.就我而言,它将是:

mutate(df, r = dense_rank(interaction(x,y,lex.order=T)))
Run Code Online (Sandbox Code Playgroud)

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


arv*_*000 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
Run Code Online (Sandbox Code Playgroud)

您可以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)
Run Code Online (Sandbox Code Playgroud)