在 R 中创建等级变量的有效方法

Efficient way to create rank variables in R

我想在我的数据框中创建几个排名变量。首先,我想要最好的排名方式。

假设我有这样的数据

grp<-c("sw","sw","sw","sl","sl","sl","sw","sl")
val<-c(12,2,6,4,9,15,6,4)
df<-cbind.data.frame(grp,val)

我希望对数据进行排名,以便在排名中没有中断,但平分。所以像这样:(我使用以下方法对数据进行排序:df[order(df$val),] )

  grp val rk
2  sw   2  1
4  sl   4  2.5
8  sl   4  2.5
3  sw   6  3.5
7  sw   6  3.5
5  sl   9  4
1  sw  12  5
6  sl  15  6

我知道如何让顺序不中断(通过使用 dense_rank)以及如何获得平局(使用排名),但不知道如何同时获得两者。密集排名似乎没有任何参数可以让您指定如何处理平局。

如果可能的话,我想要一些可以轻松应用于多列的东西。

在基于 R 的预购数据中:

with(df, ave(cumsum(!duplicated(val)) , val, FUN = function(x) x + (length(x) > 1)/length(x)))

[1] 1.000000 2.333333 2.333333 2.333333 3.500000 3.500000 4.000000 5.000000 6.000000

或使用 dplyr 的相同想法:

library(dplyr)

df %>%
  mutate(rk = dense_rank(val)) %>%
  group_by(val) %>%
  mutate(rk = rk + (n() > 1) / n())

# A tibble: 9 x 3
# Groups:   val [6]
  grp     val    rk
  <chr> <int> <dbl>
1 sw        2  1   
2 sl        4  2.33
3 sl        4  2.33
4 sl        4  2.33
5 sw        6  3.5 
6 sw        6  3.5 
7 sl        9  4   
8 sw       12  5   
9 sl       15  6 

数据(略有改动以添加多个副本):

df <- structure(list(grp = c("sw", "sl", "sl", "sl", "sw", "sw", "sl", 
                             "sw", "sl"), val = c(2L, 4L, 4L, 4L, 6L, 6L, 9L, 12L, 15L), rk = c(1, 
                                                                                                2.5, 2.5, 2.5, 3.5, 3.5, 4, 5, 6)), class = "data.frame", row.names = c("2", 
                                                                                                                                                                        "4", "9", "8", "3", "7", "5", "1", "6"))

使用data.table::frank()

library(data.table)
frank(df$val, ties.method = "dense") + frank(df$val) %% 1
# [1] 1.0 2.5 2.5 3.5 3.5 4.0 5.0 6.0

另一个data.table备选方案

setDT(df)
df[, rk := .GRP + if (.N > 1L) 0.5 else 0, by = val]
#    grp val  rk
# 1:  sw   2 1.0
# 2:  sl   4 2.5
# 3:  sl   4 2.5
# 4:  sw   6 3.5
# 5:  sw   6 3.5
# 6:  sl   9 4.0
# 7:  sw  12 5.0
# 8:  sl  15 6.0

可重现的数据:

df <- data.frame(
  grp = c("sw", "sl", "sl", "sw", "sw", "sl", "sw", "sl"),
  val = c(2L, 4L, 4L, 6L, 6L, 9L, 12L, 15L)
)