基于多个列计算排名,具有优先规则

Calculate rank based on several columns, with a precedence rule

我有一个这样的数据框

df <- expand.grid(0:1, 0:1, 0:1, 0:1)
df
   Var1 Var2 Var3 Var4
1     0    0    0    0
2     1    0    0    0
3     0    1    0    0
4     1    1    0    0
5     0    0    1    0
6     1    0    1    0
7     0    1    1    0
8     1    1    1    0
9     0    0    0    1
10    1    0    0    1
11    0    1    0    1
12    1    1    0    1
13    0    0    1    1
14    1    0    1    1
15    0    1    1    1
16    1    1    1    1

我正在尝试根据 Var1, Var2, Var3, Var4

上的某些条件创建一个 Rank

排名优先顺序由变量决定

如果任何行的 Var3Var4 的计数相同,则它们的排名相同。

我的期望输出

   Var1 Var2 Var3 Var4 rank
1     0    0    0    0   12
2     1    0    0    0    6
3     0    1    0    0    9
4     1    1    0    0    3
5     0    0    1    0   11
6     1    0    1    0    5
7     0    1    1    0    8
8     1    1    1    0    2
9     0    0    0    1   11
10    1    0    0    1    5
11    0    1    0    1    8
12    1    1    0    1    2
13    0    0    1    1   10
14    1    0    1    1    4
15    0    1    1    1    7
16    1    1    1    1    1

我正在尝试手动执行此操作,但效率不高

df %>%
  mutate(rank = case_when(
    Var1 == 1 & Var2 == 1 & Var3 == 1 & Var4 == 1~ "1",
    Var1 == 1 & Var2 == 1 & Var3 == 1 & Var4 == 0~ "2",
    TRUE                                     ~ ""
  ))

我想将逻辑应用于更大的数据集。有没有一种有效的方法来做到这一点?有人能指出我正确的方向吗?

我建议这是一个小技巧:

df <- expand.grid(0:1, 0:1, 0:1, 0:1)

df[,2] <- df[,2] * 10
df[,3] <- df[,3] * 100
df[,4] <- df[,4] * 100

rank <- rowSums(df)
as.numeric(as.factor(rank))

frank and frankv in data.table "接受向量、列表、data.frames 或 data.tables 作为输入”,这在这里很有用。

首先,frankv。它有一个 cols 参数,其中可以在字符向量中指定要排名的列 - 如果有许多需要以编程方式生成的列名,则很方便。它还有一个简洁的 order 论点。

library(data.table)
setDT(df)
df[ , Var34 := Var3 + Var4]
cols = c("Var1", "Var2", "Var34")
df[ , r := frankv(.SD, cols, order = -1L, ties.method = "dense")]
df[ , Var34 := NULL]

#     Var1 Var2 Var3 Var4  r
#  1:    0    0    0    0 12
#  2:    1    0    0    0  6
#  3:    0    1    0    0  9
#  4:    1    1    0    0  3
#  5:    0    0    1    0 11
#  6:    1    0    1    0  5
#  7:    0    1    1    0  8
#  8:    1    1    1    0  2
#  9:    0    0    0    1 11
# 10:    1    0    0    1  5
# 11:    0    1    0    1  8
# 12:    1    1    0    1  2
# 13:    0    0    1    1 10
# 14:    1    0    1    1  4
# 15:    0    1    1    1  7
# 16:    1    1    1    1  1

frank 便于交互使用:

df[ , r := frank(.SD, -Var1, -Var2, -Var34, ties.method = "dense")]

相关回答:How to emulate SQLs rank functions in R?;