基于多个列计算排名,具有优先规则
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
列
排名优先顺序由变量决定
- 列 Var1 具有最高优先级,如果它的值为 1,则它的排名更高
- 列 Var2 优先于 Var3、Var4
- 列 Var1 和 Var2 优先于 Var3、 Var4
- Var3 和 Var4 没有偏好,仅用作排名的计数
如果任何行的 Var3、Var4 的计数相同,则它们的排名相同。
我的期望输出是
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?;
我有一个这样的数据框
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 优先于 Var3、Var4
- 列 Var1 和 Var2 优先于 Var3、 Var4
- Var3 和 Var4 没有偏好,仅用作排名的计数
如果任何行的 Var3、Var4 的计数相同,则它们的排名相同。
我的期望输出是
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?;