Подтвердить что ты не робот

Data.table "ключевые индексы" или "групповой счетчик"

После создания ключа на таблице данных.

set.seed(12345)
DT <- data.table(x = sample(LETTERS[1:3], 10, replace = TRUE),
                 y = sample(LETTERS[1:3], 10, replace = TRUE))
setkey(DT, x, y)
DT
#       x y
#  [1,] A B
#  [2,] A B
#  [3,] B B
#  [4,] B B
#  [5,] C A
#  [6,] C A
#  [7,] C A
#  [8,] C A
#  [9,] C C
# [10,] C C

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

#       x y i
#  [1,] A B 1
#  [2,] A B 1
#  [3,] B B 2
#  [4,] B B 2
#  [5,] C A 3
#  [6,] C A 3
#  [7,] C A 3
#  [8,] C A 3
#  [9,] C C 4
# [10,] C C 4

Я думал об использовании чего-то вроде cumsum(!duplicated(DT[, key(DT), with = FALSE])), но я надеюсь, что есть лучшее решение. Я чувствую, что этот вектор может быть частью внутреннего представления таблицы, и, возможно, есть способ получить к нему доступ? Даже если это не так, что бы вы предложили?

4b9b3361

Ответ 1

Обновление. От v1.8.3 вы можете просто использовать встроенный специальный .GRP:

DT[ , i := .GRP, by = key(DT)]

См. историю более старых ответов.

Ответ 2

Я бы, наверное, просто сделал это, так как я уверен, что индексный счетчик не доступен из вызова [.data.table():

ii <- unique(DT)
ii[ , i := seq_len(nrow(ii))]
DT[ii]
#     x y i
#  1: A B 1
#  2: A B 1
#  3: B B 2
#  4: B B 2
#  5: C A 3
#  6: C A 3
#  7: C A 3
#  8: C A 3
#  9: C C 4
# 10: C C 4

Вы можете сделать это одним слоем, за счет дополнительного вызова unique.data.table():

DT[unique(DT)[ , i := seq_len(nrow(unique(DT)))]]