Эффективный способ создания переменных ранга в R - PullRequest
2 голосов
/ 08 мая 2020

Я хотел бы создать несколько переменных ранжирования в моем фрейме данных. Во-первых, мне нужен лучший способ ранжирования.

Допустим, у меня есть такие данные

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

Я знаю, как добиться отсутствия разрывов по порядку (с помощью density_rank) и как получить связи усредненные (с использованием ранга), но не то, как получить и то, и другое. Плотный ранг, похоже, не имеет аргументов, которые позволили бы вам указать, что делать со связями.

Я бы хотел что-нибудь, что можно было бы легко применить к нескольким столбцам, если это возможно.

Ответы [ 2 ]

3 голосов
/ 08 мая 2020

Использование 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)
)
3 голосов
/ 08 мая 2020

В базе 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"))
...