如何在R中制作排名列
How to make a rank column in R
我有一个包含列 M1
、M2
和 M3
的数据库。这些 M 值对应于每种方法获得的值。我现在的想法是为他们每个人制作一个排名列。对于M1
和M2
,排名将从最高值到最低值,M3
相反。我做了输出table给你看。
df1<-structure(list(M1 = c(400,300, 200, 50), M2 = c(500,200, 10, 100), M3 = c(420,330, 230, 51)), class = "data.frame", row.names = c(NA,-4L))
> df1
M1 M2 M3
1 400 500 420
2 300 200 330
3 200 10 230
4 50 100 51
输出
> df1
M1 rank M2 rank M3 rank
1 400 1 500 1 420 4
2 300 2 200 2 330 3
3 200 3 10 4 230 2
4 50 4 100 3 51 1
调整排名:
我使用了代码,但在我处理的案例中,我的排名如下所示:
使用 rank
和 relocate
:
library(dplyr)
df1 %>%
mutate(across(M1:M2, ~ rank(-.x), .names = "{.col}_rank"),
M3_rank = rank(M3)) %>%
relocate(order(colnames(.)))
M1 M1_rank M2 M2_rank M3 M3_rank
1 400 1 500 1 420 4
2 300 2 200 2 330 3
3 200 3 10 4 230 2
4 50 4 100 3 51 1
如果您的向量中有重复值,则必须选择一种方法来计算并列值。默认情况下,您获得平均排名,但您可以选择“第一”。
另一种可能性,我想你想做的是先转换为因子,然后再转换为数字,这样你就只能得到一个完整的值(而不是平均值)。
df1 <- data.frame(M1 = c(400,300, 50, 300))
df1 %>%
mutate(M1_rankAverage = rank(-M1),
M1_rankFirst = rank(-M1, ties.method = "first"),
M1_unique = as.numeric(as.factor(rank(-M1))))
M1 M1_rankAverage M1_rankFirst M1_unique
1 400 1.0 1 1
2 300 2.5 2 2
3 50 4.0 4 3
4 300 2.5 3 2
要实现此结果,我会做的是将每个 df 列转换为因子,然后再次将它们转换为数字。这可以在基本 R 中完成,但为了简单起见,我报告了 tidyverse 代码:
library(tidyverse)
df1 = df1 %>%
mutate(Rank1 = as.numeric(as.factor(M1))) %>%
mutate(Rank2 = as.numeric(as.factor(M2))) %>%
mutate(Rank3 = as.numeric(fct_rev(as.factor(M3))))
另一种可能的解决方案,基于dplyr
:
library(dplyr)
df1 %>%
mutate(across(-3, ~ dense_rank(desc(.x)), .names = "{.col}_rank"),
across(3, ~ dense_rank(.x), .names = "{.col}_rank")) %>%
relocate(sort(names(.)))
#> M1 M1_rank M2 M2_rank M3 M3_rank
#> 1 400 1 500 1 420 4
#> 2 300 2 200 2 330 3
#> 3 200 3 10 4 230 2
#> 4 50 4 100 3 51 1
我有一个包含列 M1
、M2
和 M3
的数据库。这些 M 值对应于每种方法获得的值。我现在的想法是为他们每个人制作一个排名列。对于M1
和M2
,排名将从最高值到最低值,M3
相反。我做了输出table给你看。
df1<-structure(list(M1 = c(400,300, 200, 50), M2 = c(500,200, 10, 100), M3 = c(420,330, 230, 51)), class = "data.frame", row.names = c(NA,-4L))
> df1
M1 M2 M3
1 400 500 420
2 300 200 330
3 200 10 230
4 50 100 51
输出
> df1
M1 rank M2 rank M3 rank
1 400 1 500 1 420 4
2 300 2 200 2 330 3
3 200 3 10 4 230 2
4 50 4 100 3 51 1
调整排名:
我使用了代码,但在我处理的案例中,我的排名如下所示:
使用 rank
和 relocate
:
library(dplyr)
df1 %>%
mutate(across(M1:M2, ~ rank(-.x), .names = "{.col}_rank"),
M3_rank = rank(M3)) %>%
relocate(order(colnames(.)))
M1 M1_rank M2 M2_rank M3 M3_rank
1 400 1 500 1 420 4
2 300 2 200 2 330 3
3 200 3 10 4 230 2
4 50 4 100 3 51 1
如果您的向量中有重复值,则必须选择一种方法来计算并列值。默认情况下,您获得平均排名,但您可以选择“第一”。
另一种可能性,我想你想做的是先转换为因子,然后再转换为数字,这样你就只能得到一个完整的值(而不是平均值)。
df1 <- data.frame(M1 = c(400,300, 50, 300))
df1 %>%
mutate(M1_rankAverage = rank(-M1),
M1_rankFirst = rank(-M1, ties.method = "first"),
M1_unique = as.numeric(as.factor(rank(-M1))))
M1 M1_rankAverage M1_rankFirst M1_unique
1 400 1.0 1 1
2 300 2.5 2 2
3 50 4.0 4 3
4 300 2.5 3 2
要实现此结果,我会做的是将每个 df 列转换为因子,然后再次将它们转换为数字。这可以在基本 R 中完成,但为了简单起见,我报告了 tidyverse 代码:
library(tidyverse)
df1 = df1 %>%
mutate(Rank1 = as.numeric(as.factor(M1))) %>%
mutate(Rank2 = as.numeric(as.factor(M2))) %>%
mutate(Rank3 = as.numeric(fct_rev(as.factor(M3))))
另一种可能的解决方案,基于dplyr
:
library(dplyr)
df1 %>%
mutate(across(-3, ~ dense_rank(desc(.x)), .names = "{.col}_rank"),
across(3, ~ dense_rank(.x), .names = "{.col}_rank")) %>%
relocate(sort(names(.)))
#> M1 M1_rank M2 M2_rank M3 M3_rank
#> 1 400 1 500 1 420 4
#> 2 300 2 200 2 330 3
#> 3 200 3 10 4 230 2
#> 4 50 4 100 3 51 1