在 R 中创建等级变量的有效方法
Efficient way to create rank variables in R
我想在我的数据框中创建几个排名变量。首先,我想要最好的排名方式。
假设我有这样的数据
grp<-c("sw","sw","sw","sl","sl","sl","sw","sl")
val<-c(12,2,6,4,9,15,6,4)
df<-cbind.data.frame(grp,val)
我希望对数据进行排名,以便在排名中没有中断,但平分。所以像这样:(我使用以下方法对数据进行排序:df[order(df$val),] )
grp val rk
2 sw 2 1
4 sl 4 2.5
8 sl 4 2.5
3 sw 6 3.5
7 sw 6 3.5
5 sl 9 4
1 sw 12 5
6 sl 15 6
我知道如何让顺序不中断(通过使用 dense_rank)以及如何获得平局(使用排名),但不知道如何同时获得两者。密集排名似乎没有任何参数可以让您指定如何处理平局。
如果可能的话,我想要一些可以轻松应用于多列的东西。
在基于 R 的预购数据中:
with(df, ave(cumsum(!duplicated(val)) , val, FUN = function(x) x + (length(x) > 1)/length(x)))
[1] 1.000000 2.333333 2.333333 2.333333 3.500000 3.500000 4.000000 5.000000 6.000000
或使用 dplyr
的相同想法:
library(dplyr)
df %>%
mutate(rk = dense_rank(val)) %>%
group_by(val) %>%
mutate(rk = rk + (n() > 1) / n())
# A tibble: 9 x 3
# Groups: val [6]
grp val rk
<chr> <int> <dbl>
1 sw 2 1
2 sl 4 2.33
3 sl 4 2.33
4 sl 4 2.33
5 sw 6 3.5
6 sw 6 3.5
7 sl 9 4
8 sw 12 5
9 sl 15 6
数据(略有改动以添加多个副本):
df <- structure(list(grp = c("sw", "sl", "sl", "sl", "sw", "sw", "sl",
"sw", "sl"), val = c(2L, 4L, 4L, 4L, 6L, 6L, 9L, 12L, 15L), rk = c(1,
2.5, 2.5, 2.5, 3.5, 3.5, 4, 5, 6)), class = "data.frame", row.names = c("2",
"4", "9", "8", "3", "7", "5", "1", "6"))
使用data.table::frank()
:
library(data.table)
frank(df$val, ties.method = "dense") + frank(df$val) %% 1
# [1] 1.0 2.5 2.5 3.5 3.5 4.0 5.0 6.0
另一个data.table
备选方案
setDT(df)
df[, rk := .GRP + if (.N > 1L) 0.5 else 0, by = val]
# grp val rk
# 1: sw 2 1.0
# 2: sl 4 2.5
# 3: sl 4 2.5
# 4: sw 6 3.5
# 5: sw 6 3.5
# 6: sl 9 4.0
# 7: sw 12 5.0
# 8: sl 15 6.0
可重现的数据:
df <- data.frame(
grp = c("sw", "sl", "sl", "sw", "sw", "sl", "sw", "sl"),
val = c(2L, 4L, 4L, 6L, 6L, 9L, 12L, 15L)
)
我想在我的数据框中创建几个排名变量。首先,我想要最好的排名方式。
假设我有这样的数据
grp<-c("sw","sw","sw","sl","sl","sl","sw","sl")
val<-c(12,2,6,4,9,15,6,4)
df<-cbind.data.frame(grp,val)
我希望对数据进行排名,以便在排名中没有中断,但平分。所以像这样:(我使用以下方法对数据进行排序:df[order(df$val),] )
grp val rk
2 sw 2 1
4 sl 4 2.5
8 sl 4 2.5
3 sw 6 3.5
7 sw 6 3.5
5 sl 9 4
1 sw 12 5
6 sl 15 6
我知道如何让顺序不中断(通过使用 dense_rank)以及如何获得平局(使用排名),但不知道如何同时获得两者。密集排名似乎没有任何参数可以让您指定如何处理平局。
如果可能的话,我想要一些可以轻松应用于多列的东西。
在基于 R 的预购数据中:
with(df, ave(cumsum(!duplicated(val)) , val, FUN = function(x) x + (length(x) > 1)/length(x)))
[1] 1.000000 2.333333 2.333333 2.333333 3.500000 3.500000 4.000000 5.000000 6.000000
或使用 dplyr
的相同想法:
library(dplyr)
df %>%
mutate(rk = dense_rank(val)) %>%
group_by(val) %>%
mutate(rk = rk + (n() > 1) / n())
# A tibble: 9 x 3
# Groups: val [6]
grp val rk
<chr> <int> <dbl>
1 sw 2 1
2 sl 4 2.33
3 sl 4 2.33
4 sl 4 2.33
5 sw 6 3.5
6 sw 6 3.5
7 sl 9 4
8 sw 12 5
9 sl 15 6
数据(略有改动以添加多个副本):
df <- structure(list(grp = c("sw", "sl", "sl", "sl", "sw", "sw", "sl",
"sw", "sl"), val = c(2L, 4L, 4L, 4L, 6L, 6L, 9L, 12L, 15L), rk = c(1,
2.5, 2.5, 2.5, 3.5, 3.5, 4, 5, 6)), class = "data.frame", row.names = c("2",
"4", "9", "8", "3", "7", "5", "1", "6"))
使用data.table::frank()
:
library(data.table)
frank(df$val, ties.method = "dense") + frank(df$val) %% 1
# [1] 1.0 2.5 2.5 3.5 3.5 4.0 5.0 6.0
另一个data.table
备选方案
setDT(df)
df[, rk := .GRP + if (.N > 1L) 0.5 else 0, by = val]
# grp val rk
# 1: sw 2 1.0
# 2: sl 4 2.5
# 3: sl 4 2.5
# 4: sw 6 3.5
# 5: sw 6 3.5
# 6: sl 9 4.0
# 7: sw 12 5.0
# 8: sl 15 6.0
可重现的数据:
df <- data.frame(
grp = c("sw", "sl", "sl", "sw", "sw", "sl", "sw", "sl"),
val = c(2L, 4L, 4L, 6L, 6L, 9L, 12L, 15L)
)