从R中的向量创建频率计数

Pat*_* Li 4 r vector

假设存在具有可能重复值的数值的向量

x <- c(1, 2, 3, 4, 5, 1, 2, 2, 3)
Run Code Online (Sandbox Code Playgroud)

我想创建另一个计数向量,如下所示.

  1. 它的长度和x.
  2. 对于每个唯一值x,第一个外观为1,第二个外观为2,依此类推.

我想要的新矢量是

1, 1, 1, 1, 1, 2, 2, 3, 2
Run Code Online (Sandbox Code Playgroud)

我需要一个快速的方法,因为x可能很长.

A5C*_*2T1 8

使用aveseq_along:

> x <- c(1, 2, 3, 4, 5, 1, 2, 2, 3)
> ave(x, x, FUN = seq_along)
[1] 1 1 1 1 1 2 2 3 2
Run Code Online (Sandbox Code Playgroud)

另一个需要考虑的选择是data.table.虽然这是一个更多的工作,它可能会在很长的向量上得到回报.

这是你的例子 - 看起来有点矫枉过正!

library(data.table)

x <- c(1, 2, 3, 4, 5, 1, 2, 2, 3)
DT <- data.table(id = sequence(length(x)), x, key = "id")
DT[, y := sequence(.N), by = x][, y]
# [1] 1 1 1 1 1 2 2 3 2
Run Code Online (Sandbox Code Playgroud)

但是对于10,000,000个项目的长度来说怎么样?

set.seed(1)
x2 <- sample(100, 1e7, replace = TRUE)

funAve <- function() {
  ave(x2, x2, FUN = seq_along)
}

funDT <- function() {
  DT <- data.table(id = sequence(length(x2)), x2, key = "id")
  DT[, y := sequence(.N), by = x2][, y]
}

identical(funAve(), funDT())
# [1] TRUE

library(microbenchmark)
# Unit: seconds
#      expr      min       lq   median       uq      max neval
#  funAve() 6.727557 6.792743 6.827117 6.992609 7.352666    20
#   funDT() 1.967795 2.029697 2.053886 2.070462 2.123531    20
Run Code Online (Sandbox Code Playgroud)