我遇到了一个需要一个多小时才能运行的简单循环,需要帮助才能加快速度。
基本上,我有一个包含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参数,这就是为什么我不想重建矩阵或拆分它。
非常感谢您的支持!
克里斯
答案 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 要长。