【问题标题】:Calculate rank based on several columns, with a precedence rule [duplicate]基于多列计算排名,具有优先规则[重复]
【发布时间】:2020-07-09 17:28:45
【问题描述】:

我有一个这样的数据框

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

排名优先顺序由变量决定

  • Var1 具有最高的偏好,如果它的值为 1,那么它的排名更高
  • Var2列优先于Var3Var4
  • Var1Var2 优先于 Var3Var4
  • Var3Var4 没有优先级,仅用作排名计数

如果任何行的 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                                     ~ ""
  ))

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

【问题讨论】:

    标签: r dplyr data.table ranking rank


    【解决方案1】:

    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?; Rank based on several variables

    【讨论】:

    • 感谢这个解决方案 :-) data.table 继续以其简单性和执行力让我感到惊讶。我现在将您的逻辑应用于我的大型数据框。我会报告的
    • 它在我更大的数据集上完美运行。非常感谢你:-)
    【解决方案2】:

    我建议这是一个小技巧:

    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))
    

    【讨论】:

    • 仅供参考 apply(df, 1, sum) 相当于 rowSums(df)
    猜你喜欢
    • 2018-02-15
    • 2017-01-14
    • 1970-01-01
    • 2017-01-04
    • 1970-01-01
    • 1970-01-01
    • 2023-01-03
    • 2018-05-18
    • 2014-03-04
    相关资源
    最近更新 更多