R:从向量的增加部分中提取频率序列(列联表)

R: extract sequence of frequencies (contingency tables) from increasing parts of a vector

我有一个包含 n 个元素的向量 V,每个元素可以是 1 到 N 之间的整数。给定这个向量,我想构造一个 N×n 矩阵 W,其中第 i 列包含整数的频率在 1 和 N 之间,因为它们出现在子向量 V[1:i].

例如,假设N=5和n=7,并且V=c(3,1,4,1,2,1,4)。然后我的矩阵 W 会有元素

0,1,1,2,2,3,3  
0,0,0,0,1,1,1  
1,1,1,1,1,1,1  
0,0,1,1,1,1,2  
0,0,0,0,0,0,0  

因为整数1(第一行)出现:0次在V[1],1次在V[1:2],1次在V[1:3],2次在V[1:4],2次在 V[1:5] 中,在 V[1:6] 中三次,在 V[1:7] 中三次,等等

我可以使用 for 循环,例如使用 tablefactor

N <- 5
n <- 7
V <- c(3,1,4,1,2,1,4)
W <- matrix(NA,N,n)

for(i in 1:n){
    W[,i] <- as.vector(table(factor(V[1:i], levels=1:N)))
}

这实际上给出了

     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]    0    1    1    2    2    3    3
[2,]    0    0    0    0    1    1    1
[3,]    1    1    1    1    1    1    1
[4,]    0    0    1    1    1    1    2
[5,]    0    0    0    0    0    0    0

但我想知道是否有一些不使用 for 循环的更聪明、更快的方法:我的 N 和 n 的数量级为 100 或 1000。

也欢迎任何其他改进上述代码的见解(我对 R 的知识仍然很基础)。

干杯!

基数为 R 的一个选项是:

V <- c(3, 1, 4, 1, 2, 1, 4)
N <- 5

sapply(seq_along(V), 
       function(i) sapply(seq_len(N), function(j) sum(V[seq_len(i)] == j)))

#      [,1] [,2] [,3] [,4] [,5] [,6] [,7]
# [1,]    0    1    1    2    2    3    3
# [2,]    0    0    0    0    1    1    1
# [3,]    1    1    1    1    1    1    1
# [4,]    0    0    1    1    1    1    2
# [5,]    0    0    0    0    0    0    0

工作原理
seq_along(V):这是 1:length(V) 的包装器,即它 returns 一个从 1 到向量 V 长度的向量。如果你确定,你的向量 V 是非空的您也可以在此处使用 1:length(V)(或在您的情况下使用 1:n

seq_len(N):类似于seq_along,但returns 1:N。如果你确定 n 是非负的,那么你也可以使用 1:N.

sapply:这是令人敬畏的 *apply 家族的一个函数。它接受一个向量或列表,并将指定的函数应用于此 vector/list 的每个元素。 sapply returns 一个简单的结构,在我们的例子中是一个用于内部应用调用的向量和一个用于完整调用的矩阵。

sum(V[seq_len(i)] == j):这里我们对逻辑向量求和,它将每个 'sub-vector' V[1:i]j 进行比较。通过对逻辑向量求和,我们只需计算 TRUEs.

的数量