首页 > 解决方案 > R:从向量的增加部分中提取频率序列(列联表)

问题描述

我有一个包含 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(第一行)出现:在 V[1] 中出现 0 次,在 V[1:2] 中出现一次,在 V[1:3] 中出现一次,在 V[1:4] 中出现两次,在 V[1 中出现两次: 5]、V[1:6] 中的 3 次、V[1:7] 中的 3 次等。

我可以用一个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 的了解仍然非常基础)。

干杯!

标签: rfor-loopcountfrequency-distributioncontingency

解决方案


以 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),即它返回一个向量,其序列从 1 到向量 V 的长度。如果你确定,你的向量 V 是非空的,你也可以1:length(V)在这里使用(或1:n在你的情况下)

seq_len(N): 类似seq_along,但返回1:N。如果您确定 N 是非负数,那么您也可以使用1:N.

sapply: 这是awesome *apply-family 的一个功能。它接受一个向量或列表,并将指定的函数应用于该向量/列表的每个元素。sapply返回一个简单的结构,在我们的例子中是一个用于内部 sapply-call 的向量和一个用于完整调用的矩阵。

sum(V[seq_len(i)] == j):这里我们对逻辑向量求和,它将每个“子向量”V[1:i]与进行比较j。通过对一个逻辑向量求和,我们只需计算TRUEs 的数量。


推荐阅读