从同一行中指示的列返回值

时间:2010-07-07 07:25:51

标签: r loops vectorization

我遇到了一个需要一个多小时才能运行的简单循环,需要帮助才能加快速度。

基本上,我有一个包含31列和400 000行的矩阵。前30列具有值,第31列具有列号。我需要每行检索第31列所指示的列中的值。

示例行:[26,354,72,5987 ..,461,3](这意味着第3列中的值是在(72)之后寻求的)

太慢的循环看起来像这样:

a <- rep(0,nrow(data)) #To pre-allocate memory
for (i in 1:nrow(data)) {
   a[i] <- data[i,data[i,31]]
}

我认为这会奏效:

a <- data[,data[,31]]

...但它会导致“错误:无法分配大小为2.8 Mb的矢量”。

我担心这是一个非常简单的问题,所以我花了好几个小时试图理解应用,lapply,重塑等等,但不知怎的,我无法控制R中的矢量化概念。

矩阵实际上有更多的列也会进入a参数,这就是为什么我不想重建矩阵或拆分它。

非常感谢您的支持!

克里斯

3 个答案:

答案 0 :(得分:2)

t(data[,1:30])[30*(0:399999)+data[,31]]

这是有效的,因为你可以引用数组格式和矢量格式(在这种情况下为400000 * 31长向量)的列数首先按列计数。要按行计数,请使用转置。

答案 1 :(得分:0)

矩阵的单指数表示法可能使用更少的内存。这将涉及做类似的事情:

i <- nrow(data)*(data[,31]-1) + 1:nrow(data)
a <- data[i]

下面是R中矩阵的单索引表示法的示例。在此示例中,每行最大值的索引作为随机矩阵的最后一列附加。然后使用最后一列通过单索引表示法选择每行最大​​值。

## create a random (10 x 5) matrix                                                                                                                           
M <- matrix(rpois(50,50),10,5)
## use the last column to index the maximum value of the first 5                                                                                             
## columns                                                                                                                                                   
MM <- cbind(M,apply(M,1,which.max))
##             column ID          row ID                                                                                                                     
i <- nrow(MM)*(MM[,ncol(MM)]-1) + 1:nrow(MM)
all(MM[i] == apply(M,1,max))

使用index matrix是另一种可能会使用更多内存但更清晰的选择:

ii <- cbind(1:nrow(MM),MM[,ncol(MM)])
all(MM[ii] == apply(M,1,max))

答案 2 :(得分:0)

尝试更改代码以一次处理一列:

M <- matrix(rpois(30*400000,50),400000,30)
MM <- cbind(M,apply(M,1,which.max))
a <- rep(0,nrow(MM))
for (i in 1:(ncol(MM)-1)) {
    a[MM[, ncol(MM)] == i] <- MM[MM[, ncol(MM)] == i, i]
}

如果最后一列的值为 i ,则使用列 i 中的值设置 a 中的所有元素。构建矩阵花费的时间比计算向量 a 要长。