我有一个包含列
M1
、M2
和 M3
的数据库。这些M值对应于通过每种方法获得的值。我现在的想法是为他们每个人制作一个排名列。对于M1
和M2
,排名将从最高值到最低值,而M3
则相反。我做了输出表给你看。
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
library(data.table)
# Assuming df1 is already a data.table
setDT(df1)
df1[, `:=`(
Rank1 = as.numeric(as.factor(M1)),
Rank2 = as.numeric(as.factor(M2)),
Rank3 = as.numeric(fct_rev(as.factor(M3)))
)]